From a51b70b51c82e453bf3124d19ff3e3838979319f Mon Sep 17 00:00:00 2001 From: goro Date: Thu, 18 Dec 2008 12:51:08 +0100 Subject: [PATCH 001/230] Bump version from 0.9.1 to 0.9.2 --- src/app/Info.plist | 4 ++-- src/plugins/bineditor/BinEditor.pluginspec | 6 +++--- src/plugins/bookmarks/Bookmarks.pluginspec | 8 ++++---- .../CMakeProjectManager.pluginspec | 12 ++++++------ src/plugins/coreplugin/Core.pluginspec | 2 +- src/plugins/coreplugin/coreconstants.h | 2 +- src/plugins/cpaster/CodePaster.pluginspec | 8 ++++---- src/plugins/cppeditor/CppEditor.pluginspec | 8 ++++---- src/plugins/cpptools/CppTools.pluginspec | 8 ++++---- src/plugins/debugger/Debugger.pluginspec | 10 +++++----- src/plugins/designer/Designer.pluginspec | 6 +++--- src/plugins/find/Find.pluginspec | 4 ++-- src/plugins/git/ScmGit.pluginspec | 10 +++++----- src/plugins/helloworld/HelloWorld.pluginspec | 4 ++-- src/plugins/help/Help.pluginspec | 8 ++++---- src/plugins/perforce/Perforce.pluginspec | 10 +++++----- .../projectexplorer/ProjectExplorer.pluginspec | 10 +++++----- .../qt4projectmanager/Qt4ProjectManager.pluginspec | 12 ++++++------ src/plugins/qtscripteditor/QtScriptEditor.pluginspec | 6 +++--- src/plugins/quickopen/QuickOpen.pluginspec | 4 ++-- src/plugins/regexp/RegExp.pluginspec | 4 ++-- src/plugins/resourceeditor/ResourceEditor.pluginspec | 4 ++-- src/plugins/snippets/Snippets.pluginspec | 8 ++++---- src/plugins/subversion/Subversion.pluginspec | 10 +++++----- src/plugins/texteditor/TextEditor.pluginspec | 8 ++++---- src/plugins/vcsbase/VCSBase.pluginspec | 8 ++++---- 26 files changed, 92 insertions(+), 92 deletions(-) diff --git a/src/app/Info.plist b/src/app/Info.plist index dbd50d35ee1..43dd8e772f5 100644 --- a/src/app/Info.plist +++ b/src/app/Info.plist @@ -182,8 +182,8 @@ CFBundleIdentifier com.nokia.qtcreator CFBundleVersion - 0.9.1 + 0.9.2 CFBundleShortVersionString - 0.9.1 + 0.9.2 diff --git a/src/plugins/bineditor/BinEditor.pluginspec b/src/plugins/bineditor/BinEditor.pluginspec index 4c79a18f251..499dc23e10b 100644 --- a/src/plugins/bineditor/BinEditor.pluginspec +++ b/src/plugins/bineditor/BinEditor.pluginspec @@ -1,11 +1,11 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Binary editor component. http://www.trolltech.com/ - - + + diff --git a/src/plugins/bookmarks/Bookmarks.pluginspec b/src/plugins/bookmarks/Bookmarks.pluginspec index e6ef924e483..35f196fb9cb 100644 --- a/src/plugins/bookmarks/Bookmarks.pluginspec +++ b/src/plugins/bookmarks/Bookmarks.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Bookmarks in text editors. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec index 84eefae0ee8..567839e781b 100644 --- a/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec +++ b/src/plugins/cmakeprojectmanager/CMakeProjectManager.pluginspec @@ -1,14 +1,14 @@ - + Nokia Corporation (C) 2008 Nokia Corporation ### TODO CMake support http://www.trolltech.com/ - - - - - + + + + + diff --git a/src/plugins/coreplugin/Core.pluginspec b/src/plugins/coreplugin/Core.pluginspec index ef7a7e38f0a..e771f21ec2f 100644 --- a/src/plugins/coreplugin/Core.pluginspec +++ b/src/plugins/coreplugin/Core.pluginspec @@ -1,4 +1,4 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License diff --git a/src/plugins/coreplugin/coreconstants.h b/src/plugins/coreplugin/coreconstants.h index 41e00202e53..857dd5be370 100644 --- a/src/plugins/coreplugin/coreconstants.h +++ b/src/plugins/coreplugin/coreconstants.h @@ -41,7 +41,7 @@ namespace Constants { #define IDE_VERSION_MAJOR 0 #define IDE_VERSION_MINOR 9 -#define IDE_VERSION_RELEASE 1 +#define IDE_VERSION_RELEASE 2 #define STRINGIFY_INTERNAL(x) #x #define STRINGIFY(x) STRINGIFY_INTERNAL(x) diff --git a/src/plugins/cpaster/CodePaster.pluginspec b/src/plugins/cpaster/CodePaster.pluginspec index 7f3e1261af8..4d03eff8e3e 100644 --- a/src/plugins/cpaster/CodePaster.pluginspec +++ b/src/plugins/cpaster/CodePaster.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Codepaster plugin for pushing/fetching diff from server http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/cppeditor/CppEditor.pluginspec b/src/plugins/cppeditor/CppEditor.pluginspec index 992f655d95b..c7fcd714e4f 100644 --- a/src/plugins/cppeditor/CppEditor.pluginspec +++ b/src/plugins/cppeditor/CppEditor.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License C/C++ editor component. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/cpptools/CppTools.pluginspec b/src/plugins/cpptools/CppTools.pluginspec index 08690446e25..1ddf6664544 100644 --- a/src/plugins/cpptools/CppTools.pluginspec +++ b/src/plugins/cpptools/CppTools.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Tools for analyzing C/C++ code. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/debugger/Debugger.pluginspec b/src/plugins/debugger/Debugger.pluginspec index 399ac3c231a..b646c0bca20 100644 --- a/src/plugins/debugger/Debugger.pluginspec +++ b/src/plugins/debugger/Debugger.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Debugger integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/designer/Designer.pluginspec b/src/plugins/designer/Designer.pluginspec index bc57324c4fb..7428e6df660 100644 --- a/src/plugins/designer/Designer.pluginspec +++ b/src/plugins/designer/Designer.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Qt Designer integration. http://www.trolltech.com/ - + - + diff --git a/src/plugins/find/Find.pluginspec b/src/plugins/find/Find.pluginspec index 2dd9dba1a8c..f0e00617e10 100644 --- a/src/plugins/find/Find.pluginspec +++ b/src/plugins/find/Find.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Provides the find widget and the hooks for find implementations. http://www.trolltech.com/ - + diff --git a/src/plugins/git/ScmGit.pluginspec b/src/plugins/git/ScmGit.pluginspec index 53f6184b80c..21c0c39ab60 100644 --- a/src/plugins/git/ScmGit.pluginspec +++ b/src/plugins/git/ScmGit.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Git integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/helloworld/HelloWorld.pluginspec b/src/plugins/helloworld/HelloWorld.pluginspec index dab4cbfd3c8..54743ced9a3 100644 --- a/src/plugins/helloworld/HelloWorld.pluginspec +++ b/src/plugins/helloworld/HelloWorld.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Hello World sample plugin. http://www.trolltech.com/ - + diff --git a/src/plugins/help/Help.pluginspec b/src/plugins/help/Help.pluginspec index dfd438522a3..50c5863b8c9 100644 --- a/src/plugins/help/Help.pluginspec +++ b/src/plugins/help/Help.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Help system. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/perforce/Perforce.pluginspec b/src/plugins/perforce/Perforce.pluginspec index 496e420c36e..21df190d99a 100644 --- a/src/plugins/perforce/Perforce.pluginspec +++ b/src/plugins/perforce/Perforce.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Perforce integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/projectexplorer/ProjectExplorer.pluginspec b/src/plugins/projectexplorer/ProjectExplorer.pluginspec index a60bbdf2949..aaecd57de93 100644 --- a/src/plugins/projectexplorer/ProjectExplorer.pluginspec +++ b/src/plugins/projectexplorer/ProjectExplorer.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License ProjectExplorer framework that can be extended with different kind of project types. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec index c5d09426de0..c928239ed8b 100644 --- a/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec +++ b/src/plugins/qt4projectmanager/Qt4ProjectManager.pluginspec @@ -1,14 +1,14 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Provides project type for Qt 4 pro files and tools. http://www.trolltech.com/ - - - - - + + + + + diff --git a/src/plugins/qtscripteditor/QtScriptEditor.pluginspec b/src/plugins/qtscripteditor/QtScriptEditor.pluginspec index f303e35e454..1cb3129b81e 100644 --- a/src/plugins/qtscripteditor/QtScriptEditor.pluginspec +++ b/src/plugins/qtscripteditor/QtScriptEditor.pluginspec @@ -1,11 +1,11 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Editor for QtScript. http://www.trolltech.com/ - - + + diff --git a/src/plugins/quickopen/QuickOpen.pluginspec b/src/plugins/quickopen/QuickOpen.pluginspec index 088f2affc95..85d9a5cc476 100644 --- a/src/plugins/quickopen/QuickOpen.pluginspec +++ b/src/plugins/quickopen/QuickOpen.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Provides the QuickOpen widget and the hooks for QuickOpen filter implementations. http://www.trolltech.com/ - + diff --git a/src/plugins/regexp/RegExp.pluginspec b/src/plugins/regexp/RegExp.pluginspec index c284def7f3a..e0c4ac44c20 100644 --- a/src/plugins/regexp/RegExp.pluginspec +++ b/src/plugins/regexp/RegExp.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Regular Expression test widget. http://www.trolltech.com/ - + diff --git a/src/plugins/resourceeditor/ResourceEditor.pluginspec b/src/plugins/resourceeditor/ResourceEditor.pluginspec index e46b249dbf4..fc7911e67cd 100644 --- a/src/plugins/resourceeditor/ResourceEditor.pluginspec +++ b/src/plugins/resourceeditor/ResourceEditor.pluginspec @@ -1,10 +1,10 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Editor for qrc files. http://www.trolltech.com/ - + diff --git a/src/plugins/snippets/Snippets.pluginspec b/src/plugins/snippets/Snippets.pluginspec index 9128dc76e9a..f7e0a18c2a0 100644 --- a/src/plugins/snippets/Snippets.pluginspec +++ b/src/plugins/snippets/Snippets.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Code snippet plugin. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/subversion/Subversion.pluginspec b/src/plugins/subversion/Subversion.pluginspec index bddb93aba6c..4e9c76c118d 100644 --- a/src/plugins/subversion/Subversion.pluginspec +++ b/src/plugins/subversion/Subversion.pluginspec @@ -1,13 +1,13 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Subversion integration. http://www.trolltech.com/ - - - - + + + + diff --git a/src/plugins/texteditor/TextEditor.pluginspec b/src/plugins/texteditor/TextEditor.pluginspec index 5c9506925cf..5f7d9a66ce7 100644 --- a/src/plugins/texteditor/TextEditor.pluginspec +++ b/src/plugins/texteditor/TextEditor.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Text editor framework and the implementation of the basic text editor. http://www.trolltech.com/ - - - + + + diff --git a/src/plugins/vcsbase/VCSBase.pluginspec b/src/plugins/vcsbase/VCSBase.pluginspec index 1f9cd30dd2d..87e3ae9eac8 100644 --- a/src/plugins/vcsbase/VCSBase.pluginspec +++ b/src/plugins/vcsbase/VCSBase.pluginspec @@ -1,12 +1,12 @@ - + Nokia Corporation (C) 2008 Nokia Corporation Nokia Beta Version License Version Control System Base Plugin http://www.trolltech.com/ - - - + + + From 355160e56f1d3a30b4a572be0254e4bf6eb923db Mon Sep 17 00:00:00 2001 From: lowinu Date: Thu, 18 Dec 2008 13:23:05 +0100 Subject: [PATCH 002/230] Fixes: correctly read mkspec RevBy: dt --- src/plugins/qt4projectmanager/qtversionmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index 3c3de8fd0e0..f1b9b956021 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -1075,7 +1075,7 @@ void QtVersion::updateMkSpec() const if (line.startsWith("QMAKESPEC_ORIGINAL")) { const QList &temp = line.split('='); if (temp.size() == 2) { - mkspec = temp.at(1); + mkspec = temp.at(1).trimmed(); } break; } From 17a9f1949fc6160a2996f023c1d852a4e5fd1aae Mon Sep 17 00:00:00 2001 From: goro Date: Thu, 18 Dec 2008 14:56:50 +0100 Subject: [PATCH 003/230] Fix initial jump to script's home dir --- scripts/snapshots/cleanup_snapshots.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/snapshots/cleanup_snapshots.sh b/scripts/snapshots/cleanup_snapshots.sh index f239cc1af0e..db283edd441 100755 --- a/scripts/snapshots/cleanup_snapshots.sh +++ b/scripts/snapshots/cleanup_snapshots.sh @@ -2,8 +2,8 @@ ## Open script-dir-homed subshell ( -ABS_SCRIPT_DIR=`pwd`/`dirname "$0"` -cd "${ABS_SCRIPT_DIR}" +ABS_SCRIPT_DIR=$(cd $(dirname $(which "$0")) && pwd) +cd "${ABS_SCRIPT_DIR}" || exit 1 ## Internal config From 2274ceb47dd80c0eb893ee1d6747f88a23e9adcb Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 16 Dec 2008 10:33:40 +0100 Subject: [PATCH 004/230] Expand $(VAR)-style environment variables Task: 229217 --- shared/proparser/profileevaluator.cpp | 15 ++++++++++++--- shared/proparser/proparserutils.h | 7 ++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index b7c296420af..723c6e2216f 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -1713,7 +1713,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct ok = false; break; } - QString msg = args.first(); + QString msg = fixEnvVariables(args.first()); if (function == QLatin1String("error")) { QStringList parents; foreach (ProFile *proFile, m_profileStack) @@ -2085,14 +2085,23 @@ bool ProFileEvaluator::contains(const QString &variableName) const return d->m_valuemap.contains(variableName); } +inline QStringList fixEnvVariables(const QStringList &x) +{ + QStringList ret; + foreach (const QString &str, x) + ret << Option::fixString(str, Option::FixEnvVars); + return ret; +} + + QStringList ProFileEvaluator::values(const QString &variableName) const { - return d->values(variableName); + return fixEnvVariables(d->values(variableName)); } QStringList ProFileEvaluator::values(const QString &variableName, const ProFile *pro) const { - return d->values(variableName, pro); + return fixEnvVariables(d->values(variableName, pro)); } ProFileEvaluator::TemplateType ProFileEvaluator::templateType() diff --git a/shared/proparser/proparserutils.h b/shared/proparser/proparserutils.h index daab115a447..6705ffad39f 100644 --- a/shared/proparser/proparserutils.h +++ b/shared/proparser/proparserutils.h @@ -173,7 +173,12 @@ static QStringList replaceInList(const QStringList &varList, const QRegExp ®e } */ -inline QStringList splitPathList(const QString paths) +inline QString fixEnvVariables(const QString &x) +{ + return Option::fixString(x, Option::FixEnvVars); +} + +inline QStringList splitPathList(const QString &paths) { return paths.split(Option::dirlist_sep); } From 72d965e2d38243bb700745684a23a82f5dfbf761 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 16 Dec 2008 10:48:49 +0100 Subject: [PATCH 005/230] Fixes: processing of else branches --- shared/proparser/profileevaluator.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index 723c6e2216f..2efbbe90b5c 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -530,11 +530,15 @@ bool ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block) if (!m_skipLevel) { m_prevCondition = m_condition; m_condition = ConditionFalse; + } else { + Q_ASSERT(m_condition != ConditionTrue); } } else if (block->blockKind() & ProBlock::ScopeContentsKind) { m_updateCondition = false; if (m_condition != ConditionTrue) ++m_skipLevel; + else + Q_ASSERT(!m_skipLevel); } return true; } @@ -542,8 +546,14 @@ bool ProFileEvaluator::Private::visitBeginProBlock(ProBlock *block) bool ProFileEvaluator::Private::visitEndProBlock(ProBlock *block) { if (block->blockKind() & ProBlock::ScopeContentsKind) { - if (m_skipLevel) + if (m_skipLevel) { + Q_ASSERT(m_condition != ConditionTrue); --m_skipLevel; + } else { + // Conditionals contained inside this block may have changed the state. + // So we reset it here to make an else following us do the right thing. + m_condition = ConditionTrue; + } } return true; } @@ -572,8 +582,12 @@ bool ProFileEvaluator::Private::visitProCondition(ProCondition *cond) { if (!m_skipLevel) { if (cond->text().toLower() == QLatin1String("else")) { + // The state ConditionElse makes sure that subsequential elses are ignored. + // That's braindead, but qmake is like that. if (m_prevCondition == ConditionTrue) m_condition = ConditionElse; + else if (m_prevCondition == ConditionFalse) + m_condition = ConditionTrue; } else if (m_condition == ConditionFalse) { if (isActiveConfig(cond->text(), true) ^ m_invertNext) m_condition = ConditionTrue; From 7112e48d520b1e80c70e49925585518ce1a1fab1 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 17 Dec 2008 14:36:59 +0100 Subject: [PATCH 006/230] disable cumulative mode for .prf files. --- shared/proparser/profileevaluator.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index 2efbbe90b5c..babcb698fb9 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -1989,7 +1989,13 @@ bool ProFileEvaluator::Private::evaluateFeatureFile(const QString &fileName, boo break; } } - return fn.isEmpty() ? false : evaluateFile(fn, result); + if (fn.isEmpty()) + return false; + bool cumulative = m_cumulative; + m_cumulative = false; + bool ok = evaluateFile(fn, result); + m_cumulative = cumulative; + return ok; } void ProFileEvaluator::Private::expandPatternHelper(const QString &relName, const QString &absName, From 35225c44dc05adc51699ba318b00a7568d79818b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 17 Dec 2008 18:47:12 +0100 Subject: [PATCH 007/230] partially sync test functions with qmake - include all known functions into the map - some of them are actually enabled - constant_names ~= s,CF_,T_, --- shared/proparser/profileevaluator.cpp | 91 +++++++++++++++++++++------ 1 file changed, 72 insertions(+), 19 deletions(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index babcb698fb9..433076a88dc 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -1570,7 +1570,7 @@ QStringList ProFileEvaluator::Private::evaluateExpandFunction(const QString &fun } break; case 0: - q->logMessage(format("'%1' is not a function").arg(func)); + q->logMessage(format("'%1' is not a recognized replace function").arg(func)); break; default: q->logMessage(format("Function '%1' is not implemented").arg(func)); @@ -1591,26 +1591,67 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct for (int i = 0; i < argumentsList.count(); ++i) args += expandVariableReferences(argumentsList[i]).join(sep); - enum ConditionFunc { CF_CONFIG = 1, CF_CONTAINS, CF_COUNT, CF_EXISTS, CF_INCLUDE, - CF_LOAD, CF_ISEMPTY, CF_SYSTEM, CF_MESSAGE}; + enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS, + T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM, + T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE, + T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_MESSAGE, T_IF }; static QHash *functions = 0; if (!functions) { functions = new QHash; - functions->insert(QLatin1String("load"), CF_LOAD); //v - functions->insert(QLatin1String("include"), CF_INCLUDE); //v - functions->insert(QLatin1String("message"), CF_MESSAGE); //v - functions->insert(QLatin1String("warning"), CF_MESSAGE); //v - functions->insert(QLatin1String("error"), CF_MESSAGE); //v + functions->insert(QLatin1String("requires"), T_REQUIRES); + functions->insert(QLatin1String("greaterThan"), T_GREATERTHAN); + functions->insert(QLatin1String("lessThan"), T_LESSTHAN); + functions->insert(QLatin1String("equals"), T_EQUALS); + functions->insert(QLatin1String("isEqual"), T_EQUALS); + functions->insert(QLatin1String("exists"), T_EXISTS); + functions->insert(QLatin1String("export"), T_EXPORT); + functions->insert(QLatin1String("clear"), T_CLEAR); + functions->insert(QLatin1String("unset"), T_UNSET); + functions->insert(QLatin1String("eval"), T_EVAL); + functions->insert(QLatin1String("CONFIG"), T_CONFIG); + functions->insert(QLatin1String("if"), T_IF); + functions->insert(QLatin1String("isActiveConfig"), T_CONFIG); + functions->insert(QLatin1String("system"), T_SYSTEM); + functions->insert(QLatin1String("return"), T_RETURN); + functions->insert(QLatin1String("break"), T_BREAK); + functions->insert(QLatin1String("next"), T_NEXT); + functions->insert(QLatin1String("defined"), T_DEFINED); + functions->insert(QLatin1String("contains"), T_CONTAINS); + functions->insert(QLatin1String("infile"), T_INFILE); + functions->insert(QLatin1String("count"), T_COUNT); + functions->insert(QLatin1String("isEmpty"), T_ISEMPTY); + functions->insert(QLatin1String("load"), T_LOAD); //v + functions->insert(QLatin1String("include"), T_INCLUDE); //v + functions->insert(QLatin1String("debug"), T_DEBUG); + functions->insert(QLatin1String("message"), T_MESSAGE); //v + functions->insert(QLatin1String("warning"), T_MESSAGE); //v + functions->insert(QLatin1String("error"), T_MESSAGE); //v } bool cond = false; bool ok = true; - ConditionFunc func_t = (ConditionFunc)functions->value(function); + TestFunc func_t = (TestFunc)functions->value(function); switch (func_t) { - case CF_CONFIG: { +#if 0 + case T_INFILE: + case T_REQUIRES: + case T_GREATERTHAN: + case T_LESSTHAN: + case T_EQUALS: + case T_EXPORT: + case T_CLEAR: + case T_UNSET: + case T_EVAL: + case T_IF: + case T_RETURN: + case T_BREAK: + case T_NEXT: + case T_DEFINED: +#endif + case T_CONFIG: { if (args.count() < 1 || args.count() > 2) { q->logMessage(format("CONFIG(config) requires one or two arguments.")); ok = false; @@ -1632,7 +1673,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } break; } - case CF_CONTAINS: { + case T_CONTAINS: { if (args.count() < 2 || args.count() > 3) { q->logMessage(format("contains(var, val) requires two or three arguments.")); ok = false; @@ -1664,9 +1705,9 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } - case CF_COUNT: { + case T_COUNT: { if (args.count() != 2 && args.count() != 3) { - q->logMessage(format("count(var, count) requires two or three arguments.")); + q->logMessage(format("count(var, count, op=\"equals\") requires two or three arguments.")); ok = false; break; } @@ -1691,7 +1732,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct cond = values(args.first()).count() == args[1].toInt(); break; } - case CF_INCLUDE: { + case T_INCLUDE: { QString parseInto; if (args.count() == 2) { parseInto = args[1]; @@ -1707,7 +1748,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct ok = evaluateFile(fileName, &ok); break; } - case CF_LOAD: { + case T_LOAD: { QString parseInto; bool ignore_error = false; if (args.count() == 2) { @@ -1721,7 +1762,10 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct ok = evaluateFeatureFile( args.first(), &cond); break; } - case CF_MESSAGE: { + case T_DEBUG: + // Yup - do nothing. Nothing is going to enable debug output anyway. + break; + case T_MESSAGE: { if (args.count() != 1) { q->logMessage(format("%1(message) requires one argument.").arg(function)); ok = false; @@ -1744,7 +1788,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } break; } - case CF_SYSTEM: { +#if 0 // Way too dangerous to enable. + case T_SYSTEM: { if (args.count() != 1) { q->logMessage(format("system(exec) requires one argument.")); ok = false; @@ -1753,7 +1798,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct ok = system(args.first().toLatin1().constData()) == 0; break; } - case CF_ISEMPTY: { +#endif + case T_ISEMPTY: { if (args.count() != 1) { q->logMessage(format("isEmpty(var) requires one argument.")); ok = false; @@ -1768,7 +1814,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } break; } - case CF_EXISTS: { + case T_EXISTS: { if (args.count() != 1) { q->logMessage(format("exists(file) requires one argument.")); ok = false; @@ -1792,6 +1838,13 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } + case 0: + // This is too chatty currently (missing defineTest and defineReplace) + //q->logMessage(format("'%1' is not a recognized test function").arg(function)); + break; + default: + q->logMessage(format("Function '%1' is not implemented").arg(function)); + break; } if (result) From 6522b4b5a25c9ed9fd7a03a1e75e91adf51cc317 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 17 Dec 2008 18:52:14 +0100 Subject: [PATCH 008/230] handle skipping of test functions on a per-function basis now we process all includes and loads in cumulative mode again. functions without side effects don't need special attention in the first place, obviously. and the printing functions already have their own handling. --- shared/proparser/profileevaluator.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index 433076a88dc..ea280b45b4d 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -821,7 +821,7 @@ bool ProFileEvaluator::Private::visitProValue(ProValue *value) bool ProFileEvaluator::Private::visitProFunction(ProFunction *func) { - if (!m_skipLevel && (!m_updateCondition || m_condition == ConditionFalse)) { + if (!m_updateCondition || m_condition == ConditionFalse) { QString text = func->text(); int lparen = text.indexOf(QLatin1Char('(')); int rparen = text.lastIndexOf(QLatin1Char(')')); @@ -829,10 +829,12 @@ bool ProFileEvaluator::Private::visitProFunction(ProFunction *func) QString arguments = text.mid(lparen + 1, rparen - lparen - 1); QString funcName = text.left(lparen); m_lineNo = func->lineNumber(); - bool result = false; - if (!evaluateConditionalFunction(funcName.trimmed(), arguments, &result)) + bool result; + if (!evaluateConditionalFunction(funcName.trimmed(), arguments, &result)) { + m_invertNext = false; return false; - if (result ^ m_invertNext) + } + if (!m_skipLevel && (result ^ m_invertNext)) m_condition = ConditionTrue; } m_invertNext = false; @@ -1733,6 +1735,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } case T_INCLUDE: { + if (m_skipLevel && !m_cumulative) + break; QString parseInto; if (args.count() == 2) { parseInto = args[1]; @@ -1749,6 +1753,8 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } case T_LOAD: { + if (m_skipLevel && !m_cumulative) + break; QString parseInto; bool ignore_error = false; if (args.count() == 2) { From 719894044d8b79cb24934747c0b7b8d1cbb9330f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Thu, 18 Dec 2008 16:56:43 +0100 Subject: [PATCH 009/230] Keep completion popup on the screen Pop it upwards when it would otherwise go below the screen and shift it to the left when it would otherwise exit the screen on the right. --- src/plugins/texteditor/basetexteditor.cpp | 1 - src/plugins/texteditor/completionwidget.cpp | 37 ++++++++++++++------- src/plugins/texteditor/completionwidget.h | 2 +- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp index 48de83d5ef2..ea4f665a7e9 100644 --- a/src/plugins/texteditor/basetexteditor.cpp +++ b/src/plugins/texteditor/basetexteditor.cpp @@ -1603,7 +1603,6 @@ namespace TextEditor { int firstColumn; int lastColumn; }; - } } diff --git a/src/plugins/texteditor/completionwidget.cpp b/src/plugins/texteditor/completionwidget.cpp index 661cda0c322..f9057d39078 100644 --- a/src/plugins/texteditor/completionwidget.cpp +++ b/src/plugins/texteditor/completionwidget.cpp @@ -39,8 +39,9 @@ #include #include -#include #include +#include +#include #include #include @@ -130,6 +131,8 @@ CompletionWidget::CompletionWidget(CompletionSupport *support, ITextEditable *ed layout->addWidget(this); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_popupFrame->setMinimumSize(1, 1); + setMinimumSize(1, 1); } bool CompletionWidget::event(QEvent *e) @@ -227,20 +230,15 @@ void CompletionWidget::setCompletionItems(const QListcursorRect(startPos).bottomLeft(); - m_popupFrame->move(pos.x() - 16, pos.y()); - m_popupFrame->setMinimumSize(1, 1); - setMinimumSize(1, 1); - - updateSize(); - + updatePositionAndSize(startPos); m_popupFrame->show(); show(); setFocus(); } -void CompletionWidget::updateSize() +void CompletionWidget::updatePositionAndSize(int startPos) { + // Determine size by calculating the space of the visible items int visibleItems = m_model->rowCount(); if (visibleItems > NUMBER_OF_VISIBLE_ITEMS) visibleItems = NUMBER_OF_VISIBLE_ITEMS; @@ -254,10 +252,25 @@ void CompletionWidget::updateSize() shint = tmp; } - const int width = (shint.width() + (m_popupFrame->frameWidth() * 2) + 30); - const int height = (shint.height() * visibleItems) + m_popupFrame->frameWidth() * 2; + const int frameWidth = m_popupFrame->frameWidth(); + const int width = shint.width() + frameWidth * 2 + 30; + const int height = shint.height() * visibleItems + frameWidth * 2; - m_popupFrame->resize(width, height); + // Determine the position, keeping the popup on the screen + const QRect cursorRect = m_editor->cursorRect(startPos); + const QDesktopWidget *desktop = QApplication::desktop(); + const QRect screen = desktop->availableGeometry(desktop->screenNumber(this)); + + QPoint pos = cursorRect.bottomLeft(); + pos.rx() -= 16 + frameWidth; // Space for the icons + + if (pos.y() + height > screen.bottom()) + pos.setY(cursorRect.top() - height); + + if (pos.x() + width > screen.right()) + pos.setX(screen.right() - width); + + m_popupFrame->setGeometry(pos.x(), pos.y(), width, height); } void CompletionWidget::completionActivated(const QModelIndex &index) diff --git a/src/plugins/texteditor/completionwidget.h b/src/plugins/texteditor/completionwidget.h index c1fb28fc1cf..b124d2e257a 100644 --- a/src/plugins/texteditor/completionwidget.h +++ b/src/plugins/texteditor/completionwidget.h @@ -74,7 +74,7 @@ private slots: void completionActivated(const QModelIndex &index); private: - void updateSize(); + void updatePositionAndSize(int startPos); QPointer m_popupFrame; bool m_blockFocusOut; From c6004485de8d0f37c11da7f64d28ef92991c5acb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 18 Dec 2008 17:19:54 +0100 Subject: [PATCH 010/230] Fixes: Make Goto Slot work. Task: 205821 Details: Do not look only in the source file, but also in the first order includes for the class definition. Polish and simplify the thing a bit, do not check for Ui_foo. --- src/plugins/designer/workbenchintegration.cpp | 390 +++++++++++------- 1 file changed, 236 insertions(+), 154 deletions(-) diff --git a/src/plugins/designer/workbenchintegration.cpp b/src/plugins/designer/workbenchintegration.cpp index 8483c2f1d9a..0291bd21058 100644 --- a/src/plugins/designer/workbenchintegration.cpp +++ b/src/plugins/designer/workbenchintegration.cpp @@ -59,6 +59,7 @@ #include enum { debugSlotNavigation = 0 }; +enum { indentation = 4 }; using namespace Designer::Internal; using namespace CPlusPlus; @@ -75,6 +76,12 @@ static QString msgClassNotFound(const QString &uiClassName, const QListgetObject(); + return core->pluginManager()->getObject(); +} + WorkbenchIntegration::WorkbenchIntegration(QDesignerFormEditorInterface *core, FormEditorW *parent) : qdesigner_internal::QDesignerIntegration(core, ::qobject_cast(parent)), m_few(parent) @@ -101,18 +108,13 @@ QWidget *WorkbenchIntegration::containerWindow(QWidget * /*widget*/) const return fw->integrationContainer(); } -static QList findDocumentsIncluding(const QString &fileName, bool checkFileNameOnly) +static QList findDocumentsIncluding(const CPlusPlus::Snapshot &docTable, + const QString &fileName, bool checkFileNameOnly) { - Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); - CppTools::CppModelManagerInterface *cppModelManager = - core->pluginManager()->getObject(); - QList docList; - // take all docs - CPlusPlus::Snapshot docTable = cppModelManager->snapshot(); - foreach (Document::Ptr doc, docTable) { // we go through all documents - QStringList includes = doc->includedFiles(); - foreach (QString include, includes) { + foreach (const Document::Ptr &doc, docTable) { // we go through all documents + const QStringList includes = doc->includedFiles(); + foreach (const QString &include, includes) { if (checkFileNameOnly) { const QFileInfo fi(include); if (fi.fileName() == fileName) { // we are only interested in docs which includes fileName only @@ -127,78 +129,79 @@ static QList findDocumentsIncluding(const QString &fileName, bool return docList; } -static Class *findClass(Namespace *parentNameSpace, const QString &uiClassName, QString *namespaceName) +// Check for a class name where haystack is a member class of an object. +// So, haystack can be shorter (can have some namespaces omitted because of a +// "using namespace" declaration, for example, comparing +// "foo::Ui::form", against "using namespace foo; Ui::form". + +static bool matchMemberClassName(const QString &needle, const QString &hayStack) { - // construct proper ui class name, take into account namespaced ui class name - QString className1; - QString className2; - int indexOfScope = uiClassName.lastIndexOf(QLatin1String("::")); - if (indexOfScope < 0) { - className1 = QLatin1String("Ui::") + uiClassName; - className2 = QLatin1String("Ui_") + uiClassName; - } else { - className1 = uiClassName.left(indexOfScope + 2) + QLatin1String("Ui::") + uiClassName.mid(indexOfScope + 2); - className2 = uiClassName.left(indexOfScope + 2) + QLatin1String("Ui_") + uiClassName.mid(indexOfScope + 2); - } + if (needle == hayStack) + return true; + if (!needle.endsWith(hayStack)) + return false; + // Check if there really is a separator "::" + const int separatorPos = needle.size() - hayStack.size() - 1; + return separatorPos > 1 && needle.at(separatorPos) == QLatin1Char(':'); +} - for (unsigned i = 0; i < parentNameSpace->memberCount(); i++) { // we go through all namespace members - if (Class *cl = parentNameSpace->memberAt(i)->asClass()) { // we have found a class - we are interested in classes only - Overview o; - QString className = o.prettyName(cl->name()); - for (unsigned j = 0; j < cl->memberCount(); j++) { // we go through class members - const Declaration *decl = cl->memberAt(j)->asDeclaration(); - if (decl) { // we want to know if the class contains a member (so we look into a declaration) of uiClassName type - NamedType *nt = decl->type()->asNamedType(); +// Find class definition in namespace +static const Class *findClass(const Namespace *parentNameSpace, const QString &className, QString *namespaceName) +{ + if (debugSlotNavigation) + qDebug() << Q_FUNC_INFO << className; + const Overview o; + const unsigned namespaceMemberCount = parentNameSpace->memberCount(); + for (unsigned i = 0; i < namespaceMemberCount; i++) { // we go through all namespace members + const Symbol *sym = parentNameSpace->memberAt(i); + // we have found a class - we are interested in classes only + if (const Class *cl = sym->asClass()) { + const unsigned classMemberCount = cl->memberCount(); + for (unsigned j = 0; j < classMemberCount; j++) // we go through class members + if (const Declaration *decl = cl->memberAt(j)->asDeclaration()) { + // we want to know if the class contains a member (so we look into + // a declaration) of uiClassName type + const NamedType *nt = decl->type()->asNamedType(); // handle pointers to member variables if (PointerType *pt = decl->type()->asPointerType()) nt = pt->elementType()->asNamedType(); - if (nt) { - Overview typeOverview; - const QString memberClass = typeOverview.prettyName(nt->name()); - if (memberClass == className1 || memberClass == className2) // names match + if (nt && matchMemberClassName(className, o.prettyName(nt->name()))) return cl; - // memberClass can be shorter (can have some namespaces cut because of e.g. "using namespace" declaration) - if (memberClass == className1.right(memberClass.length())) { // memberClass lenght <= className length - const QString namespacePrefix = className1.left(className1.length() - memberClass.length()); - if (namespacePrefix.right(2) == QLatin1String("::")) - return cl; - } - // the same as above but for className2 - if (memberClass == className2.right(memberClass.length())) { // memberClass lenght <= className length - const QString namespacePrefix = className2.left(className1.length() - memberClass.length()); - if (namespacePrefix.right(2) == QLatin1String("::")) - return cl; - } - } + } // decl + } else { + // Check namespaces + if (const Namespace *ns = sym->asNamespace()) { + QString tempNS = *namespaceName; + tempNS += o.prettyName(ns->name()); + tempNS += QLatin1String("::"); + if (const Class *cl = findClass(ns, className, &tempNS)) { + *namespaceName = tempNS; + return cl; } - } - } else if (Namespace *ns = parentNameSpace->memberAt(i)->asNamespace()) { - Overview o; - QString tempNS = *namespaceName + o.prettyName(ns->name()) + QLatin1String("::"); - Class *cl = findClass(ns, uiClassName, &tempNS); - if (cl) { - *namespaceName = tempNS; - return cl; - } - } - } + } // member is namespave + } // member is no class + } // for members return 0; } -static Function *findDeclaration(Class *cl, const QString &functionName) +static const Function *findDeclaration(const Class *cl, const QString &functionName) { const QString funName = QString::fromUtf8(QMetaObject::normalizedSignature(functionName.toUtf8())); - for (unsigned j = 0; j < cl->memberCount(); j++) { // go through all members - const Declaration *decl = cl->memberAt(j)->asDeclaration(); - if (decl) { // we are interested only in declarations (can be decl of method or of a field) - Function *fun = decl->type()->asFunction(); - if (fun) { // we are only interested in declarations of methods - Overview overview; - QString memberFunction = overview.prettyName(fun->name()) + QLatin1Char('('); - for (uint i = 0; i < fun->argumentCount(); i++) { // we build argument types string - Argument *arg = fun->argumentAt(i)->asArgument(); + const unsigned mCount = cl->memberCount(); + // we are interested only in declarations (can be decl of method or of a field) + // we are only interested in declarations of methods + const Overview overview; + for (unsigned j = 0; j < mCount; j++) { // go through all members + if (const Declaration *decl = cl->memberAt(j)->asDeclaration()) + if (const Function *fun = decl->type()->asFunction()) { + // Format signature + QString memberFunction = overview.prettyName(fun->name()); + memberFunction += QLatin1Char('('); + const uint aCount = fun->argumentCount(); + for (uint i = 0; i < aCount; i++) { // we build argument types string + const Argument *arg = fun->argumentAt(i)->asArgument(); if (i > 0) memberFunction += QLatin1Char(','); memberFunction += overview.prettyType(arg->type()); @@ -209,19 +212,18 @@ static Function *findDeclaration(Class *cl, const QString &functionName) if (memberFunction == funName) // we match function names and argument lists return fun; } - } } return 0; } // TODO: remove me, see below -static bool isCompatible(Name *name, Name *otherName) +static bool isCompatible(const Name *name, const Name *otherName) { - if (NameId *nameId = name->asNameId()) { - if (TemplateNameId *otherTemplId = otherName->asTemplateNameId()) + if (const NameId *nameId = name->asNameId()) { + if (const TemplateNameId *otherTemplId = otherName->asTemplateNameId()) return nameId->identifier()->isEqualTo(otherTemplId->identifier()); - } else if (TemplateNameId *templId = name->asTemplateNameId()) { - if (NameId *otherNameId = otherName->asNameId()) + } else if (const TemplateNameId *templId = name->asTemplateNameId()) { + if (const NameId *otherNameId = otherName->asNameId()) return templId->identifier()->isEqualTo(otherNameId->identifier()); } @@ -229,7 +231,7 @@ static bool isCompatible(Name *name, Name *otherName) } // TODO: remove me, see below -static bool isCompatible(Function *definition, Symbol *declaration, QualifiedNameId *declarationName) +static bool isCompatible(const Function *definition, const Symbol *declaration, const QualifiedNameId *declarationName) { Function *declTy = declaration->type()->asFunction(); if (! declTy) @@ -269,11 +271,9 @@ static bool isCompatible(Function *definition, Symbol *declaration, QualifiedNam } // TODO: remove me, this is taken from cppeditor.cpp. Find some common place for this method -static Document::Ptr findDefinition(Function *functionDeclaration, int *line) +static Document::Ptr findDefinition(const Function *functionDeclaration, int *line) { - Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); - CppTools::CppModelManagerInterface *cppModelManager = - core->pluginManager()->getObject(); + CppTools::CppModelManagerInterface *cppModelManager = cppModelManagerInstance(); if (!cppModelManager) return Document::Ptr(); @@ -286,7 +286,8 @@ static Document::Ptr findDefinition(Function *functionDeclaration, int *line) if (QualifiedNameId *q = scopeOwnerName->asQualifiedNameId()) { for (unsigned i = 0; i < q->nameCount(); ++i) { qualifiedName.prepend(q->nameAt(i)); - } + +} } else { qualifiedName.prepend(scopeOwnerName); } @@ -299,7 +300,6 @@ static Document::Ptr findDefinition(Function *functionDeclaration, int *line) Control control; QualifiedNameId *q = control.qualifiedNameId(&qualifiedName[0], qualifiedName.size()); LookupContext context(&control); - const Snapshot documents = cppModelManager->snapshot(); foreach (Document::Ptr doc, documents) { QList visibleScopes; @@ -368,71 +368,80 @@ static int findClassEndPosition(const QString &headerContents, int classStartPos return -1; } -static void addDeclaration(const QString &docFileName, Class *cl, const QString &functionName) +static inline ITextEditable *editableAt(const QString &fileName, int line, int column) { - // functionName comes already with argument names (if designer managed to do that) - for (unsigned j = 0; j < cl->memberCount(); j++) { // go through all members - const Declaration *decl = cl->memberAt(j)->asDeclaration(); - if (decl) { // we want to find any method which is a private slot (then we don't need to add "private slots:" statement) - Function *fun = decl->type()->asFunction(); - if (fun) { // we are only interested in declarations of methods + return qobject_cast(TextEditor::BaseTextEditor::openEditorAt(fileName, line, column)); +} + +static void addDeclaration(const QString &docFileName, const Class *cl, const QString &functionName) +{ + QString declaration = QLatin1String("void "); + declaration += functionName; + declaration += QLatin1String(";\n"); + + // functionName comes already with argument names (if designer managed to + // do that). First, let's try to find any method which is a private slot + // (then we don't need to add "private slots:" statement) + const unsigned mCount = cl->memberCount(); + for (unsigned j = 0; j < mCount; j++) { // go through all members + if (const Declaration *decl = cl->memberAt(j)->asDeclaration()) + if (const Function *fun = decl->type()->asFunction()) { + // we are only interested in declarations of methods. + // fun->column() returns always 0, what can cause trouble in case in one + // line if there is: "private slots: void foo();" if (fun->isSlot() && fun->isPrivate()) { - ITextEditable *editable = qobject_cast( - TextEditor::BaseTextEditor::openEditorAt(docFileName, fun->line(), fun->column())); - // fun->column() raturns always 0, what can cause trouble in case in one - // line there is: "private slots: void foo();" - if (editable) { - editable->insert(QLatin1String("void ") + functionName + QLatin1String(";\n ")); - } + if (ITextEditable *editable = editableAt(docFileName, fun->line(), fun->column())) + editable->insert(declaration + QLatin1String(" ")); return; } } - } } // We didn't find any method under "private slots:", let's add "private slots:". Below code // adds "private slots:" by the end of the class definition. - ITextEditable *editable = qobject_cast( - TextEditor::BaseTextEditor::openEditorAt(docFileName, cl->line(), cl->column())); - if (editable) { + if (ITextEditable *editable = editableAt(docFileName, cl->line(), cl->column())) { int classEndPosition = findClassEndPosition(editable->contents(), editable->position()); if (classEndPosition >= 0) { int line, column; editable->convertPosition(classEndPosition, &line, &column); // converts back position into a line and column editable->gotoLine(line, column); // go to position (we should be just before closing } of the class) - editable->insert(QLatin1String("\nprivate slots:\n ") - + QLatin1String("void ") + functionName + QLatin1String(";\n")); + editable->insert(QLatin1String("\nprivate slots:\n ") + declaration); } } } -static Document::Ptr addDefinition(const QString &headerFileName, const QString &className, - const QString &functionName, int *line) +static Document::Ptr addDefinition(const CPlusPlus::Snapshot &docTable, + const QString &headerFileName, const QString &className, + const QString &functionName, int *line) { + QString definition = QLatin1String("\nvoid "); + definition += className; + definition += QLatin1String("::"); + definition += functionName; + definition += QLatin1String("\n{\n"); + definition += QString(indentation, QLatin1Char(' ')); + definition += QLatin1String("\n}\n"); + // we find all documents which include headerFileName - QList docList = findDocumentsIncluding(headerFileName, false); + const QList docList = findDocumentsIncluding(docTable, headerFileName, false); if (docList.isEmpty()) return Document::Ptr(); QFileInfo headerFI(headerFileName); const QString headerBaseName = headerFI.baseName(); const QString headerAbsolutePath = headerFI.absolutePath(); - foreach (Document::Ptr doc, docList) { - QFileInfo sourceFI(doc->fileName()); + foreach (const Document::Ptr &doc, docList) { + const QFileInfo sourceFI(doc->fileName()); // we take only those documents which has the same filename and path (maybe we don't need to compare the path???) if (headerBaseName == sourceFI.baseName() && headerAbsolutePath == sourceFI.absolutePath()) { - ITextEditable *editable = qobject_cast( - TextEditor::BaseTextEditor::openEditorAt(doc->fileName(), 0)); - if (editable) { + if (ITextEditable *editable = editableAt(doc->fileName(), 0, 0)) { const QString contents = editable->contents(); int column; editable->convertPosition(contents.length(), line, &column); editable->gotoLine(*line, column); - editable->insert(QLatin1String("\nvoid ") + className + QLatin1String("::") + - functionName + QLatin1String("\n {\n\n }\n")); + editable->insert(definition); *line += 1; - } return doc; } @@ -440,33 +449,84 @@ static Document::Ptr addDefinition(const QString &headerFileName, const QString return Document::Ptr(); } +// Insert the parameter names into a signature, "void foo(bool)" -> +// "void foo(bool checked)" static QString addParameterNames(const QString &functionSignature, const QStringList ¶meterNames) { - QString functionName = functionSignature.left(functionSignature.indexOf(QLatin1Char('(')) + 1); - QString argumentsString = functionSignature.mid(functionSignature.indexOf(QLatin1Char('(')) + 1); - argumentsString = argumentsString.left(argumentsString.indexOf(QLatin1Char(')'))); + const int firstParen = functionSignature.indexOf(QLatin1Char('(')); + QString functionName = functionSignature.left(firstParen + 1); + QString argumentsString = functionSignature.mid(firstParen + 1); + const int lastParen = argumentsString.lastIndexOf(QLatin1Char(')')); + if (lastParen != -1) + argumentsString.truncate(lastParen); const QStringList arguments = argumentsString.split(QLatin1Char(','), QString::SkipEmptyParts); - for (int i = 0; i < arguments.count(); ++i) { + const int pCount = parameterNames.count(); + const int aCount = arguments.count(); + for (int i = 0; i < aCount; ++i) { if (i > 0) functionName += QLatin1String(", "); functionName += arguments.at(i); - if (i < parameterNames.count()) - functionName += QLatin1Char(' ') + parameterNames.at(i); + if (i < pCount) { + functionName += QLatin1Char(' '); + functionName += parameterNames.at(i); + } } functionName += QLatin1Char(')'); return functionName; } +// Recursively find a class definition in the document passed on or in its +// included files (going down [maxIncludeDepth] includes) and return a pair +// of . + +typedef QPair ClassDocumentPtrPair; + +static ClassDocumentPtrPair + findClassRecursively(const CPlusPlus::Snapshot &docTable, + const Document::Ptr &doc, const QString &className, + unsigned maxIncludeDepth, QString *namespaceName) +{ + if (debugSlotNavigation) + qDebug() << Q_FUNC_INFO << doc->fileName() << maxIncludeDepth; + // Check document + if (const Class *cl = findClass(doc->globalNamespace(), className, namespaceName)) + return ClassDocumentPtrPair(cl, doc); + if (maxIncludeDepth) { + // Check the includes + const unsigned recursionMaxIncludeDepth = maxIncludeDepth - 1u; + foreach (const QString &include, doc->includedFiles()) { + const CPlusPlus::Snapshot::const_iterator it = docTable.constFind(include); + if (it != docTable.constEnd()) { + const Document::Ptr includeDoc = it.value(); + const ClassDocumentPtrPair irc = findClassRecursively(docTable, it.value(), className, recursionMaxIncludeDepth, namespaceName); + if (irc.first) + return irc; + } + } + } + return ClassDocumentPtrPair(0, Document::Ptr()); +} void WorkbenchIntegration::slotNavigateToSlot(const QString &objectName, const QString &signalSignature, const QStringList ¶meterNames) { QString errorMessage; if (!navigateToSlot(objectName, signalSignature, parameterNames, &errorMessage) && !errorMessage.isEmpty()) { - QMessageBox::critical(m_few->designerEditor()->topLevel(), tr("Error finding source file"), errorMessage); + QMessageBox::warning(m_few->designerEditor()->topLevel(), tr("Error finding/adding a slot."), errorMessage); } } +// Build name of the class as generated by uic, insert Ui namespace +// "foo::bar::form" -> "foo::bar::Ui::form" + +static inline QString uiClassName(QString formObjectName) +{ + const int indexOfScope = formObjectName.lastIndexOf(QLatin1String("::")); + const int uiNameSpaceInsertionPos = indexOfScope >= 0 ? indexOfScope : 0; + formObjectName.insert(uiNameSpaceInsertionPos, QLatin1String("Ui::")); + return formObjectName; +} + bool WorkbenchIntegration::navigateToSlot(const QString &objectName, const QString &signalSignature, const QStringList ¶meterNames, @@ -482,7 +542,10 @@ bool WorkbenchIntegration::navigateToSlot(const QString &objectName, const QFileInfo fi(currentUiFile); const QString uicedName = QLatin1String("ui_") + fi.baseName() + QLatin1String(".h"); - QList docList = findDocumentsIncluding(uicedName, true); // change to false when we know the absolute path to generated ui_<>.h file + // take all docs + + const CPlusPlus::Snapshot docTable = cppModelManagerInstance()->snapshot(); + QList docList = findDocumentsIncluding(docTable, uicedName, true); // change to false when we know the absolute path to generated ui_<>.h file if (debugSlotNavigation) qDebug() << objectName << signalSignature << "Looking for " << uicedName << " returned " << docList.size(); @@ -493,44 +556,63 @@ bool WorkbenchIntegration::navigateToSlot(const QString &objectName, QDesignerFormWindowInterface *fwi = m_few->activeFormWindow()->formWindow(); - const QString uiClassName = fwi->mainContainer()->objectName(); + const QString uiClass = uiClassName(fwi->mainContainer()->objectName()); if (debugSlotNavigation) - qDebug() << "Checking docs for " << uiClassName; + qDebug() << "Checking docs for " << uiClass; - foreach (const Document::Ptr &doc, docList) { - QString namespaceName; // namespace of the class found - Class *cl = findClass(doc->globalNamespace(), uiClassName, &namespaceName); - if (cl) { - Overview o; - const QString className = namespaceName + o.prettyName(cl->name()); + // Find the class definition in the file itself or in the directly + // included files (order 1). + QString namespaceName; + const Class *cl; + Document::Ptr doc; - QString functionName = QLatin1String("on_") + objectName + QLatin1Char('_') + signalSignature; - QString functionNameWithParameterNames = addParameterNames(functionName, parameterNames); - Function *fun = findDeclaration(cl, functionName); - int line = 0; - Document::Ptr sourceDoc; - if (!fun) { - // add function declaration to cl - addDeclaration(doc->fileName(), cl, functionNameWithParameterNames); - - // add function definition to cpp file - sourceDoc = addDefinition(doc->fileName(), className, functionNameWithParameterNames, &line); - } else { - sourceDoc = findDefinition(fun, &line); - if (!sourceDoc) { - // add function definition to cpp file - sourceDoc = addDefinition(doc->fileName(), className, functionNameWithParameterNames, &line); - } - } - if (sourceDoc) { - // jump to function definition - TextEditor::BaseTextEditor::openEditorAt(sourceDoc->fileName(), line); - } - return true; + foreach (const Document::Ptr &d, docList) { + const ClassDocumentPtrPair cd = findClassRecursively(docTable, d, uiClass, 1u , &namespaceName); + if (cd.first) { + cl = cd.first; + doc = cd.second; + break; } } - *errorMessage = msgClassNotFound(uiClassName, docList); - return false; -} + if (!cl) { + *errorMessage = msgClassNotFound(uiClass, docList); + return false; + } + Overview o; + const QString className = namespaceName + o.prettyName(cl->name()); + + const QString functionName = QLatin1String("on_") + objectName + QLatin1Char('_') + signalSignature; + const QString functionNameWithParameterNames = addParameterNames(functionName, parameterNames); + + if (debugSlotNavigation) + qDebug() << "Found " << uiClass << doc->fileName() << " checking " << functionName << functionNameWithParameterNames; + + int line = 0; + Document::Ptr sourceDoc; + + if (const Function *fun = findDeclaration(cl, functionName)) { + sourceDoc = findDefinition(fun, &line); + if (!sourceDoc) { + // add function definition to cpp file + sourceDoc = addDefinition(docTable, doc->fileName(), className, functionNameWithParameterNames, &line); + } + } else { + // add function declaration to cl + addDeclaration(doc->fileName(), cl, functionNameWithParameterNames); + + // add function definition to cpp file + sourceDoc = addDefinition(docTable, doc->fileName(), className, functionNameWithParameterNames, &line); + } + + if (!sourceDoc) { + *errorMessage = tr("Unable to add the method definition."); + return false; + } + + // jump to function definition, position within code + TextEditor::BaseTextEditor::openEditorAt(sourceDoc->fileName(), line + 2, indentation); + + return true; +} From 6049e1fbb4cf1982e44e265725aa5255318eb389 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 09:15:02 +0100 Subject: [PATCH 011/230] small dumper refactoring oin the way to "all dumper code in gdbmacros.cpp" --- bin/gdbmacros/gdbmacros.cpp | 2 +- src/plugins/debugger/gdbengine.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp index 0802d54a70a..c58e83abf01 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -2465,6 +2465,7 @@ void qDumpObjectData440( "\""NS"QObjectSlot\"," "\""NS"QObjectSlotList\"," #endif // PRIVATE_OBJECT_ALLOWED + // << "\""NS"QRegion\"," "\""NS"QSet\"," "\""NS"QString\"," "\""NS"QStringList\"," @@ -2480,7 +2481,6 @@ void qDumpObjectData440( "\"std::string\"," "\"std::vector\"," "\"std::wstring\"," - // << "\""NS"QRegion\"," "]"; d << ",namespace=\""NS"\""; d.disarm(); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 957a223db47..002e643c136 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -2961,11 +2961,11 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) // in rare cases we need more or less: if (outertype == m_namespace + "QObject") { - extraArgs[extraArgCount++] = "(char*)&((('" + extraArgs[0] = "(char*)&((('" + m_namespace + "QObjectPrivate'*)&" + data.exp + ")->children)-(char*)&" + data.exp; } else if (outertype == m_namespace + "QVector") { - extraArgs[extraArgCount++] = "(char*)&((" + extraArgs[1] = "(char*)&((" + data.exp + ").d->array)-(char*)" + data.exp + ".d"; } else if (outertype == m_namespace + "QObjectSlot" || outertype == m_namespace + "QObjectSignal") { @@ -2976,16 +2976,16 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) QString slotNumber = "-1"; if (lastOpened != -1 && lastClosed != -1) slotNumber = data.iname.mid(lastOpened + 1, lastClosed - lastOpened - 1); - extraArgs[extraArgCount++] = slotNumber; + extraArgs[0] = slotNumber; } else if (outertype == m_namespace + "QMap") { QString nodetype = m_namespace + "QMapNode"; nodetype += data.type.mid(m_namespace.size() + 4); //qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype; - extraArgs[extraArgCount++] = sizeofTypeExpression(nodetype); - extraArgs[extraArgCount++] = "(size_t)&(('" + nodetype + "'*)0)->value"; + extraArgs[2] = sizeofTypeExpression(nodetype); + extraArgs[3] = "(size_t)&(('" + nodetype + "'*)0)->value"; } else if (outertype == m_namespace + "QMapNode") { - extraArgs[extraArgCount++] = sizeofTypeExpression(data.type); - extraArgs[extraArgCount++] = "(size_t)&(('" + data.type + "'*)0)->value"; + extraArgs[2] = sizeofTypeExpression(data.type); + extraArgs[3] = "(size_t)&(('" + data.type + "'*)0)->value"; } else if (outertype == "std::vector") { //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners; if (inners.at(0) == "bool") { From e970f43da76c1a23987f760ee6c0bb63d5204542 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 19 Dec 2008 10:34:33 +0100 Subject: [PATCH 012/230] Fixes: Put the Ui:: class in the same namespace as the form class (was broken for namespaces) --- .../cpp/formclasswizardparameters.cpp | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/plugins/designer/cpp/formclasswizardparameters.cpp b/src/plugins/designer/cpp/formclasswizardparameters.cpp index 19fdd7f3527..2441cddc3a0 100644 --- a/src/plugins/designer/cpp/formclasswizardparameters.cpp +++ b/src/plugins/designer/cpp/formclasswizardparameters.cpp @@ -62,8 +62,15 @@ bool FormClassWizardParameters::generateCpp(QString *header, QString *source, in return false; } + // Build the ui class (Ui::Foo) name relative to the namespace (which is the same): + const QString colonColon = QLatin1String("::"); + const int lastSeparator = uiClassName.lastIndexOf(colonColon); + if (lastSeparator != -1) + uiClassName.remove(0, lastSeparator + colonColon.size()); + uiClassName.insert(0, QLatin1String(uiNamespaceC) + colonColon); + // Do we have namespaces? - QStringList namespaceList = className.split(QLatin1String("::")); + QStringList namespaceList = className.split(colonColon); if (namespaceList.empty()) // Paranoia! return false; @@ -94,18 +101,21 @@ bool FormClassWizardParameters::generateCpp(QString *header, QString *source, in } } + const QString namespaceIndent = Core::Utils::writeOpeningNameSpaces(namespaceList, indent, headerStr); + // Forward-declare the UI class if (embedding == PointerAggregatedUiClass) { - headerStr << "\nnamespace " << uiNamespaceC << " {\n" - << indent << "class " << uiClassName << ";\n}\n"; + headerStr << '\n' + << namespaceIndent << "namespace " << uiNamespaceC << " {\n" + << namespaceIndent << indent << "class " << FormTemplateWizardPagePage::stripNamespaces(uiClassName) << ";\n" + << namespaceIndent << "}\n"; } - const QString namespaceIndent = Core::Utils::writeOpeningNameSpaces(namespaceList, indent, headerStr); // Class declaration headerStr << '\n' << namespaceIndent << "class " << unqualifiedClassName << " : public " << formBaseClass; if (embedding == InheritedUiClass) { - headerStr << ", private " << uiNamespaceC << "::" << uiClassName; + headerStr << ", private " << uiClassName; } headerStr << " {\n" << namespaceIndent << indent << "Q_OBJECT\n" << namespaceIndent << indent << "Q_DISABLE_COPY(" << unqualifiedClassName << ")\n" @@ -120,7 +130,7 @@ bool FormClassWizardParameters::generateCpp(QString *header, QString *source, in // Member variable if (embedding != InheritedUiClass) { headerStr << '\n' << namespaceIndent << "private:\n" - << namespaceIndent << indent << uiNamespaceC << "::" << uiClassName << ' '; + << namespaceIndent << indent << uiClassName << ' '; if (embedding == PointerAggregatedUiClass) headerStr << '*'; headerStr << uiMemberC << ";\n"; @@ -140,7 +150,7 @@ bool FormClassWizardParameters::generateCpp(QString *header, QString *source, in sourceStr << '\n' << namespaceIndent << unqualifiedClassName << "::" << unqualifiedClassName << "(QWidget *parent) :\n" << namespaceIndent << indent << formBaseClass << "(parent)"; if (embedding == PointerAggregatedUiClass) - sourceStr << ",\n" << namespaceIndent << indent << uiMemberC << "(new " << uiNamespaceC << "::" << uiClassName << ")\n"; + sourceStr << ",\n" << namespaceIndent << indent << uiMemberC << "(new " << uiClassName << ")\n"; sourceStr << namespaceIndent << "{\n" << namespaceIndent << indent; if (embedding != InheritedUiClass) sourceStr << uiMemberC << (embedding == PointerAggregatedUiClass ? "->" : "."); From d6fbb1b5730eac0b06ee6bfcbae71075ab6e57bd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 19 Dec 2008 10:49:29 +0100 Subject: [PATCH 013/230] Fixes: gcc 4.3.2 compile warnings --- src/app/main.cpp | 4 ++-- src/plugins/cmakeprojectmanager/cmakestep.cpp | 6 +++--- src/plugins/cmakeprojectmanager/makestep.cpp | 6 +++--- src/plugins/coreplugin/inavigationwidgetfactory.cpp | 4 ++-- src/plugins/git/gitclient.cpp | 2 +- src/plugins/perforce/perforceeditor.cpp | 2 +- src/plugins/qt4projectmanager/directorywatcher.cpp | 3 ++- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/app/main.cpp b/src/app/main.cpp index f11e81764d1..2efc04f1451 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -98,12 +98,12 @@ static void displayError(const QString &t) // No console on Windows. static void displayHelpText(const QString &t) { - qWarning(t.toUtf8().constData()); + qWarning("%s", qPrintable(t)); } static void displayError(const QString &t) { - qCritical(t.toUtf8().constData()); + qCritical("%s", qPrintable(t)); } #endif diff --git a/src/plugins/cmakeprojectmanager/cmakestep.cpp b/src/plugins/cmakeprojectmanager/cmakestep.cpp index 88572968040..13963273287 100644 --- a/src/plugins/cmakeprojectmanager/cmakestep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakestep.cpp @@ -99,7 +99,7 @@ QString CMakeBuildStepConfigWidget::displayName() const return "CMake"; } -void CMakeBuildStepConfigWidget::init(const QString &buildConfiguration) +void CMakeBuildStepConfigWidget::init(const QString & /*buildConfiguration */) { // TODO } @@ -121,12 +121,12 @@ ProjectExplorer::BuildStep *CMakeBuildStepFactory::create(ProjectExplorer::Proje return new CMakeStep(pro); } -QStringList CMakeBuildStepFactory::canCreateForProject(ProjectExplorer::Project *pro) const +QStringList CMakeBuildStepFactory::canCreateForProject(ProjectExplorer::Project * /* pro */) const { return QStringList(); } -QString CMakeBuildStepFactory::displayNameForName(const QString &name) const +QString CMakeBuildStepFactory::displayNameForName(const QString & /* name */) const { return "CMake"; } diff --git a/src/plugins/cmakeprojectmanager/makestep.cpp b/src/plugins/cmakeprojectmanager/makestep.cpp index 1c7e7f055f5..abd77cd10aa 100644 --- a/src/plugins/cmakeprojectmanager/makestep.cpp +++ b/src/plugins/cmakeprojectmanager/makestep.cpp @@ -93,7 +93,7 @@ QString MakeBuildStepConfigWidget::displayName() const return "Make"; } -void MakeBuildStepConfigWidget::init(const QString &buildConfiguration) +void MakeBuildStepConfigWidget::init(const QString & /* buildConfiguration */) { // TODO } @@ -115,12 +115,12 @@ ProjectExplorer::BuildStep *MakeBuildStepFactory::create(ProjectExplorer::Projec return new MakeStep(pro); } -QStringList MakeBuildStepFactory::canCreateForProject(ProjectExplorer::Project *pro) const +QStringList MakeBuildStepFactory::canCreateForProject(ProjectExplorer::Project * /* pro */) const { return QStringList(); } -QString MakeBuildStepFactory::displayNameForName(const QString &name) const +QString MakeBuildStepFactory::displayNameForName(const QString & /* name */) const { return "Make"; } diff --git a/src/plugins/coreplugin/inavigationwidgetfactory.cpp b/src/plugins/coreplugin/inavigationwidgetfactory.cpp index 885277434d7..f2ac6d8d539 100644 --- a/src/plugins/coreplugin/inavigationwidgetfactory.cpp +++ b/src/plugins/coreplugin/inavigationwidgetfactory.cpp @@ -49,12 +49,12 @@ QKeySequence INavigationWidgetFactory::activationSequence() } -void INavigationWidgetFactory::saveSettings(int position, QWidget *widget) +void INavigationWidgetFactory::saveSettings(int /* position */, QWidget * /* widget */) { } -void INavigationWidgetFactory::restoreSettings(int position, QWidget *widget) +void INavigationWidgetFactory::restoreSettings(int /* position */, QWidget * /* widget */) { } diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 3113ebf3f86..f4a0feb33e7 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -476,7 +476,7 @@ static inline QString trimFileSpecification(QString fileSpec) // Collapse the sequence of spaces const int filePos = colonIndex + 2; int nonBlankPos = filePos; - for ( ; fileSpec.at(nonBlankPos).isSpace(); nonBlankPos++); + for ( ; fileSpec.at(nonBlankPos).isSpace(); nonBlankPos++) ; if (nonBlankPos > filePos) fileSpec.remove(filePos, nonBlankPos - filePos); } diff --git a/src/plugins/perforce/perforceeditor.cpp b/src/plugins/perforce/perforceeditor.cpp index 5a0b1d2340e..d54ce10de5f 100644 --- a/src/plugins/perforce/perforceeditor.cpp +++ b/src/plugins/perforce/perforceeditor.cpp @@ -151,7 +151,7 @@ QString PerforceEditor::fileNameFromDiffSpecification(const QTextBlock &inBlock) // Ask plugin to map back const QString fileName = m_plugin->fileNameFromPerforceName(diffFileName.trimmed(), &errorMessage); if (fileName.isEmpty()) - qWarning(errorMessage.toUtf8().constData()); + qWarning("%s", qPrintable(errorMessage)); return fileName; } } diff --git a/src/plugins/qt4projectmanager/directorywatcher.cpp b/src/plugins/qt4projectmanager/directorywatcher.cpp index 3434b0284d4..e2e0828219f 100644 --- a/src/plugins/qt4projectmanager/directorywatcher.cpp +++ b/src/plugins/qt4projectmanager/directorywatcher.cpp @@ -207,7 +207,8 @@ int FileWatcher::m_objectCount = 0; QHash FileWatcher::m_fileCount; QFileSystemWatcher *FileWatcher::m_watcher = 0; -FileWatcher::FileWatcher(QObject *parent) +FileWatcher::FileWatcher(QObject *parent) : + QObject(parent) { if (!m_watcher) m_watcher = new QFileSystemWatcher(); From 4db2f99836cdf22a98609631147ebce401ef8a60 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 19 Dec 2008 11:45:30 +0100 Subject: [PATCH 014/230] Fixes: Add ensureStashed() method asking user to stash before a change such as pull --- src/plugins/git/gitclient.cpp | 83 ++++++++++++++++++++++++++++++----- src/plugins/git/gitclient.h | 8 +++- src/plugins/git/gitplugin.cpp | 13 +++++- src/plugins/git/gitplugin.h | 1 + 4 files changed, 90 insertions(+), 15 deletions(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index f4a0feb33e7..83dafdc1b66 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -379,6 +379,23 @@ bool GitClient::synchronousCheckout(const QString &workingDirectory, return true; } +bool GitClient::synchronousStash(const QString &workingDirectory, QString *errorMessage) +{ + if (Git::Constants::debug) + qDebug() << Q_FUNC_INFO << workingDirectory; + QByteArray outputText; + QByteArray errorText; + QStringList arguments; + arguments << QLatin1String("stash"); + const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText); + if (!rc) { + *errorMessage = tr("Unable stash in %1: %2").arg(workingDirectory, QString::fromLocal8Bit(errorText)); + return false; + } + return true; +} + + void GitClient::executeGit(const QString &workingDirectory, const QStringList &arguments, VCSBase::VCSBaseEditor* editor, bool outputToWindow) @@ -467,6 +484,60 @@ bool GitClient::synchronousGit(const QString &workingDirectory, return process.exitCode() == 0; } +static inline int + askWithDetailedText(QWidget *parent, + const QString &title, const QString &msg, + const QString &inf, + QMessageBox::StandardButton defaultButton, + QMessageBox::StandardButtons buttons = QMessageBox::Yes|QMessageBox::No) +{ + QMessageBox msgBox(QMessageBox::Question, title, msg, buttons, parent); + msgBox.setDetailedText(inf); + msgBox.setDefaultButton(defaultButton); + return msgBox.exec(); +} + +// Convenience that pops up an msg box. +GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory) +{ + QString errorMessage; + const StashResult sr = ensureStash(workingDirectory, &errorMessage); + if (sr == StashFailed) { + m_plugin->outputWindow()->append(errorMessage); + m_plugin->outputWindow()->popup(); + } + return sr; +} + +// Ensure that changed files are stashed before a pull or similar +GitClient::StashResult GitClient::ensureStash(const QString &workingDirectory, QString *errorMessage) +{ + QString statusOutput; + switch (gitStatus(workingDirectory, false, &statusOutput, errorMessage)) { + case StatusChanged: + break; + case StatusUnchanged: + return StashUnchanged; + case StatusFailed: + return StashFailed; + } + + const int answer = askWithDetailedText(m_core->mainWindow(), tr("Changes"), + tr("You have modified files. Would you like to stash your changes?"), + statusOutput, QMessageBox::Yes, QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel); + switch (answer) { + case QMessageBox::Cancel: + return StashCanceled; + case QMessageBox::Yes: + if (!synchronousStash(workingDirectory, errorMessage)) + return StashFailed; + break; + case QMessageBox::No: // At your own risk, so. + return NotStashed; + } + + return Stashed; + } // Trim a git status file spec: "modified: foo .cpp" -> "modified: foo .cpp" static inline QString trimFileSpecification(QString fileSpec) @@ -703,18 +774,6 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory, return rc; } -static inline bool askWithInformativeText(QWidget *parent, - const QString &title, - const QString &msg, - const QString &inf, - bool defaultValue) -{ - QMessageBox msgBox(QMessageBox::Question, title, msg, QMessageBox::Yes|QMessageBox::No, parent); - msgBox.setInformativeText(inf); - msgBox.setDefaultButton(defaultValue ? QMessageBox::Yes : QMessageBox::No); - return msgBox.exec() == QMessageBox::Yes; -} - /* Revert: This function can be called with a file list (to revert single * files) or a single directory (revert all). Qt Creator currently has only * 'revert single' in its VCS menus, but the code is prepared to deal with diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index 2ae6c3f583a..af45bbb9a36 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -92,6 +92,7 @@ public: bool synchronousReset(const QString &workingDirectory, const QStringList &files); bool synchronousReset(const QString &workingDirectory, const QStringList &files, QString *errorMessage); bool synchronousCheckout(const QString &workingDirectory, const QStringList &files, QString *errorMessage); + bool synchronousStash(const QString &workingDirectory, QString *errorMessage); void pull(const QString &workingDirectory); void push(const QString &workingDirectory); @@ -105,6 +106,11 @@ public: QString readConfigValue(const QString &workingDirectory, const QString &configVar); + enum StashResult { StashUnchanged, StashCanceled, StashFailed, + Stashed, NotStashed /* User did not want it */ }; + StashResult ensureStash(const QString &workingDirectory, QString *errorMessage); + StashResult ensureStash(const QString &workingDirectory); + bool getCommitData(const QString &workingDirectory, QString *commitTemplate, CommitData *d, @@ -118,7 +124,7 @@ public: enum StatusResult { StatusChanged, StatusUnchanged, StatusFailed }; StatusResult gitStatus(const QString &workingDirectory, - bool untracked, + bool untracked = false, QString *output = 0, QString *errorMessage = 0); diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index dc18fe088ed..85af681d209 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -703,8 +703,17 @@ bool GitPlugin::editorAboutToClose(Core::IEditor *iEditor) void GitPlugin::pull() { const QString workingDirectory = getWorkingDirectory(); - if (!workingDirectory.isEmpty()) - m_gitClient->pull(workingDirectory); + if (workingDirectory.isEmpty()) + return; + + switch (m_gitClient->ensureStash(workingDirectory)) { + case GitClient::StashUnchanged: + case GitClient::Stashed: + case GitClient::NotStashed: + m_gitClient->pull(workingDirectory); + default: + break; + } } void GitPlugin::push() diff --git a/src/plugins/git/gitplugin.h b/src/plugins/git/gitplugin.h index 5e15a52a87a..39287e1939a 100644 --- a/src/plugins/git/gitplugin.h +++ b/src/plugins/git/gitplugin.h @@ -97,6 +97,7 @@ public: GitOutputWindow *outputWindow() const; + GitSettings settings() const; void setSettings(const GitSettings &s); From 220cf0d2e230e7c1f62b521afdbd1551560d7450 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 12:20:04 +0100 Subject: [PATCH 015/230] Add some sandbox for hjkl folks. Note that is called . --- .../editormanager/editormanager.cpp | 1 + src/plugins/fakevim/FakeVim.pluginspec | 12 + src/plugins/fakevim/fakevim.pro | 19 + src/plugins/fakevim/fakevimplugin.cpp | 189 ++++++++ src/plugins/fakevim/fakevimplugin.h | 83 ++++ src/plugins/fakevim/handler.cpp | 453 ++++++++++++++++++ src/plugins/fakevim/handler.h | 70 +++ src/plugins/plugins.pro | 8 +- 8 files changed, 834 insertions(+), 1 deletion(-) create mode 100644 src/plugins/fakevim/FakeVim.pluginspec create mode 100644 src/plugins/fakevim/fakevim.pro create mode 100644 src/plugins/fakevim/fakevimplugin.cpp create mode 100644 src/plugins/fakevim/fakevimplugin.h create mode 100644 src/plugins/fakevim/handler.cpp create mode 100644 src/plugins/fakevim/handler.h diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index cb911b1fd20..1eb3abb133d 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -319,6 +319,7 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) : IActionContainer *advancedMenu = am->createMenu(Constants::M_EDIT_ADVANCED); medit->addMenu(advancedMenu, Constants::G_EDIT_FORMAT); advancedMenu->menu()->setTitle(tr("&Advanced")); + cmd = am->registerAction(m_d->m_openInExternalEditorAction, Constants::OPEN_IN_EXTERNAL_EDITOR, editManagerContext); cmd->setDefaultKeySequence(QKeySequence(tr("Alt+V,Alt+I"))); advancedMenu->addAction(cmd); diff --git a/src/plugins/fakevim/FakeVim.pluginspec b/src/plugins/fakevim/FakeVim.pluginspec new file mode 100644 index 00000000000..66a091e283d --- /dev/null +++ b/src/plugins/fakevim/FakeVim.pluginspec @@ -0,0 +1,12 @@ + + Nokia Corporation + (C) 2008 Nokia Corporation + Nokia Beta Version License + VI-style keyboard navigation. + http://www.trolltech.com/ + + + + + + diff --git a/src/plugins/fakevim/fakevim.pro b/src/plugins/fakevim/fakevim.pro new file mode 100644 index 00000000000..6a160774e6a --- /dev/null +++ b/src/plugins/fakevim/fakevim.pro @@ -0,0 +1,19 @@ +TEMPLATE = lib +TARGET = FakeVim + +# CONFIG += single +include(../../qworkbenchplugin.pri) +include(../../plugins/projectexplorer/projectexplorer.pri) +include(../../plugins/coreplugin/coreplugin.pri) +include(../../plugins/texteditor/texteditor.pri) + +# DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII +QT += gui + +SOURCES += \ + handler.cpp \ + fakevimplugin.cpp + +HEADERS += \ + handler.h \ + fakevimplugin.h diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp new file mode 100644 index 00000000000..72671a37c60 --- /dev/null +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -0,0 +1,189 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ + +#include "fakevimplugin.h" + +#include "handler.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + + +using namespace FakeVim::Internal; +//using namespace FakeVim::Constants; +using namespace TextEditor; +using namespace Core; +using namespace ProjectExplorer; + + +namespace FakeVim { +namespace Constants { + +const char * const INSTALL_HANDLER = "FakeVim.InstallHandler"; +const char * const INSTALL_KEY = "Alt+V,Alt+V"; + +} // namespace Constants +} // namespace FakeVim + + +/////////////////////////////////////////////////////////////////////// +// +// FakeVimPlugin +// +/////////////////////////////////////////////////////////////////////// + +FakeVimPlugin::FakeVimPlugin() +{ + m_pm = 0; + m_handler = 0; +} + +FakeVimPlugin::~FakeVimPlugin() +{} + +void FakeVimPlugin::shutdown() +{ + delete m_handler; + m_handler = 0; +} + +bool FakeVimPlugin::initialize(const QStringList &arguments, QString *error_message) +{ + Q_UNUSED(arguments); + Q_UNUSED(error_message); + + m_handler = new FakeVimHandler; + + m_pm = ExtensionSystem::PluginManager::instance(); + + ICore *core = m_pm->getObject(); + QTC_ASSERT(core, return false); + + Core::ActionManagerInterface *actionManager = core->actionManager(); + QTC_ASSERT(actionManager, return false); + + QList globalcontext; + globalcontext << Core::Constants::C_GLOBAL_ID; + + m_installHandlerAction = new QAction(this); + m_installHandlerAction->setText(tr("Set vi-Style Keyboard Action Handler")); + + Core::ICommand *cmd = 0; + cmd = actionManager->registerAction(m_installHandlerAction, + Constants::INSTALL_HANDLER, globalcontext); + cmd->setDefaultKeySequence(QKeySequence(Constants::INSTALL_KEY)); + + IActionContainer *advancedMenu = + actionManager->actionContainer(Core::Constants::M_EDIT_ADVANCED); + advancedMenu->addAction(cmd); + + connect(m_installHandlerAction, SIGNAL(triggered()), + this, SLOT(installHandler())); + return true; +} + +void FakeVimPlugin::extensionsInitialized() +{ +} + +void FakeVimPlugin::installHandler() +{ + ICore *core = m_pm->getObject(); + if (!core || !core->editorManager()) + return; + Core::IEditor *editor = core->editorManager()->currentEditor(); + ITextEditor *textEditor = qobject_cast(editor); + if (!textEditor) + return; + + QWidget *widget = textEditor->widget(); + QPlainTextEdit *plainTextEdit = qobject_cast(widget); + if (!plainTextEdit) + return; + plainTextEdit->removeEventFilter(m_handler); + plainTextEdit->installEventFilter(m_handler); + QFont font = plainTextEdit->font(); + //font.setFamily("Monospace"); + m_savedCursorWidth = plainTextEdit->cursorWidth(); + plainTextEdit->setCursorWidth(QFontMetrics(font).width(QChar('x'))); + + //QMainWindow mw; + connect(m_handler, SIGNAL(commandBufferChanged(QString)), + this, SLOT(showCommandBuffer(QString))); + connect(m_handler, SIGNAL(quitRequested(QObject *)), + this, SLOT(removeHandler(QObject *))); +} + +void FakeVimPlugin::removeHandler(QObject *ob) +{ + ob->removeEventFilter(m_handler); + QPlainTextEdit *plainTextEdit = qobject_cast(ob); + if (!plainTextEdit) + return; + plainTextEdit->setCursorWidth(m_savedCursorWidth); +} + +void FakeVimPlugin::showCommandBuffer(const QString &contents) +{ + //qDebug() << "CMD: " << contents; +} + + +//#include "fakevimplugin.moc" + +Q_EXPORT_PLUGIN(FakeVimPlugin) diff --git a/src/plugins/fakevim/fakevimplugin.h b/src/plugins/fakevim/fakevimplugin.h new file mode 100644 index 00000000000..f31ad1e68e6 --- /dev/null +++ b/src/plugins/fakevim/fakevimplugin.h @@ -0,0 +1,83 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ + +#ifndef FAKEVIMPLUGIN_H +#define FAKEVIMPLUGIN_H + +#include + +#include + +QT_BEGIN_NAMESPACE +class QAction; +class QCursor; +class QAbstractItemView; +QT_END_NAMESPACE + +namespace Core { class IEditor; } +namespace TextEditor { class ITextEditor; } + +namespace FakeVim { +namespace Internal { + +class FakeVimHandler; + +class FakeVimPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + +public: + FakeVimPlugin(); + ~FakeVimPlugin(); + +private: + bool initialize(const QStringList &arguments, QString *error_message); + void shutdown(); + void extensionsInitialized(); + +private slots: + void installHandler(); + void removeHandler(QObject *ob); + void showCommandBuffer(const QString &contents); + +private: + FakeVimHandler *m_handler; + ExtensionSystem::PluginManager *m_pm; + QAction *m_installHandlerAction; + int m_savedCursorWidth; +}; + +} // namespace Internal +} // namespace FakeVim + +#endif // FAKEVIMPLUGIN_H diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp new file mode 100644 index 00000000000..fbd59c26b8e --- /dev/null +++ b/src/plugins/fakevim/handler.cpp @@ -0,0 +1,453 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ + +#include "handler.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace FakeVim::Internal; + +#define StartOfLine QTextCursor::StartOfLine +#define EndOfLine QTextCursor::EndOfLine +#define MoveAnchor QTextCursor::MoveAnchor +#define KeepAnchor QTextCursor::KeepAnchor +#define Up QTextCursor::Up +#define Down QTextCursor::Down +#define Right QTextCursor::Right +#define Left QTextCursor::Left + + +/////////////////////////////////////////////////////////////////////// +// +// FakeVimHandler +// +/////////////////////////////////////////////////////////////////////// +const int ParagraphSeparator = 0x00002029; + +using namespace Qt; + +enum Mode { InsertMode, CommandMode, ExMode }; + +enum SubMode { NoSubMode, RegisterSubMode, ChangeSubMode, DeleteSubMode }; + +class FakeVimHandler::Private +{ +public: + Private(FakeVimHandler *parent); + + bool eventFilter(QObject *ob, QEvent *ev); + + static int shift(int key) { return key + 32; } + static int control(int key) { return key + 256; } + + void init(); + void handleKey(int key); + void handleInsertMode(int key); + void handleCommandMode(int key); + void handleRegisterMode(int key); + void handleExMode(int key); + void finishMovement(); + void updateCommandBuffer(); + void search(const QString &needle, bool backwards); + void showMessage(const QString &msg); + + int count() const { return m_count.isEmpty() ? 1 : m_count.toInt(); } + int leftDist() const { return m_tc.position() - m_tc.block().position(); } + int rightDist() const { return m_tc.block().length() - leftDist() - 1; } + bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; } + + FakeVimHandler *q; + Mode m_mode; + SubMode m_submode; + QString m_input; + QPlainTextEdit *m_editor; + QTextCursor m_tc; + QHash m_registers; + int m_register; + QString m_count; + + QStack m_undoStack; + QStack m_redoStack; + + bool m_fakeEnd; + + int m_commandCode; // ?, /, : ... + QString m_commandBuffer; + + bool m_lastSearchBackward; + QString m_lastSearchString; +}; + +FakeVimHandler::Private::Private(FakeVimHandler *parent) +{ + q = parent; + m_mode = CommandMode; + m_fakeEnd = false; + m_lastSearchBackward = false; + m_register = '"'; +} + +bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) +{ + QKeyEvent *keyEvent = static_cast(ev); + int key = keyEvent->key(); + if (key == Key_Shift || key == Key_Alt || key == Key_Control + || key == Key_Alt || key == Key_AltGr || key == Key_Meta) + return false; + //qDebug() << "KEY: " << key << Qt::ShiftModifier; + + // Fake "End of line" + m_editor = qobject_cast(ob); + if (!m_editor) + return false; + + m_tc = m_editor->textCursor(); + if (m_fakeEnd) { + //m_fakeEnd = false; + m_tc.movePosition(Right, MoveAnchor, 1); + qDebug() << "Unfake EOL"; + } + + if (key >= Key_A && key <= Key_Z + && (keyEvent->modifiers() & Qt::ShiftModifier) == 0) + key += 32; + if ((keyEvent->modifiers() & Qt::ControlModifier) != 0) + key += 256; + handleKey(key); + + // We fake vi-style end-of-line behaviour + m_fakeEnd = atEol() && m_mode == CommandMode; + + //qDebug() << "POS: " << m_tc.position() + // << " BLOCK LEN: " << m_tc.block().length() + // << " LEFT: " << leftDist() << " RIGHT: " << rightDist(); + + if (m_fakeEnd) { + m_tc.movePosition(Left, MoveAnchor, 1); + qDebug() << "Fake EOL"; + } + + //qDebug() << "POS: " << m_tc.position() + // << " BLOCK LEN: " << m_tc.block().length() + // << " LEFT: " << leftDist() << " RIGHT: " << rightDist(); + + m_editor->setTextCursor(m_tc); + m_editor->ensureCursorVisible(); + return true; +} + +void FakeVimHandler::Private::handleKey(int key) +{ + if (m_mode == InsertMode) + handleInsertMode(key); + else if (m_mode == CommandMode) + handleCommandMode(key); + else if (m_mode == ExMode) + handleExMode(key); +} + +void FakeVimHandler::Private::finishMovement() +{ + if (m_submode == ChangeSubMode) { + m_registers[m_register] = m_tc.selectedText(); + m_tc.removeSelectedText(); + m_mode = InsertMode; + m_submode = NoSubMode; + } else if (m_submode == DeleteSubMode) { + m_registers[m_register] = m_tc.selectedText(); + m_tc.removeSelectedText(); + m_submode = NoSubMode; + if (atEol()) + m_tc.movePosition(Left, MoveAnchor, 1); + } + m_count.clear(); + m_register = '"'; + m_tc.clearSelection(); + updateCommandBuffer(); +} + +void FakeVimHandler::Private::updateCommandBuffer() +{ + //qDebug() << "CMD" << m_commandBuffer; + QString msg = QChar(m_commandCode ? m_commandCode : ' ') + m_commandBuffer; + emit q->commandBufferChanged(msg); +} + +void FakeVimHandler::Private::showMessage(const QString &msg) +{ + emit q->commandBufferChanged(msg); +} + +void FakeVimHandler::Private::handleCommandMode(int key) +{ + //qDebug() << "-> MODE: " << m_mode << " KEY: " << key; + if (m_submode == RegisterSubMode) { + m_register = key; + m_submode = NoSubMode; + } else if (m_submode == ChangeSubMode && key == 'c') { + m_tc.movePosition(StartOfLine, MoveAnchor); + m_tc.movePosition(Down, KeepAnchor, count()); + m_registers[m_register] = m_tc.selectedText(); + finishMovement(); + } else if (m_submode == DeleteSubMode && key == 'd') { + m_tc.movePosition(StartOfLine, MoveAnchor); + m_tc.movePosition(Down, KeepAnchor, count()); + m_registers[m_register] = m_tc.selectedText(); + finishMovement(); + } else if (key >= '0' && key <= '9') { + if (key == '0' && m_count.isEmpty()) { + m_tc.movePosition(StartOfLine, KeepAnchor); + finishMovement(); + } else { + m_count.append(QChar(key)); + } + } else if (key == ':' || key == '/' || key == '?') { + m_commandCode = key; + m_mode = ExMode; + updateCommandBuffer(); + } else if (key == '|') { + m_tc.movePosition(StartOfLine, KeepAnchor); + m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist()) - 1); + finishMovement(); + } else if (key == '"') { + m_submode = RegisterSubMode; + } else if (key == Key_Return) { + m_tc.movePosition(StartOfLine); + m_tc.movePosition(Down); + } else if (key == Key_Home) { + m_tc.movePosition(StartOfLine, KeepAnchor); + finishMovement(); + } else if (key == '$' || key == Key_End) { + m_tc.movePosition(EndOfLine, KeepAnchor); + finishMovement(); + } else if (key == 'A') { + m_tc.movePosition(EndOfLine, MoveAnchor); + m_mode = InsertMode; + } else if (key == 'c') { + m_submode = ChangeSubMode; + } else if (key == 'C') { + m_submode = ChangeSubMode; + m_tc.movePosition(EndOfLine, KeepAnchor); + finishMovement(); + } else if (key == 'd') { + if (atEol()) + m_tc.movePosition(Left, MoveAnchor, 1); + m_submode = DeleteSubMode; + } else if (key == 'D') { + m_submode = DeleteSubMode; + m_tc.movePosition(EndOfLine, KeepAnchor); + finishMovement(); + } else if (key == 'h' || key == Key_Left) { + int n = qMin(count(), leftDist()); + if (m_fakeEnd && m_tc.block().length() > 1) + ++n; + m_tc.movePosition(Left, KeepAnchor, n); + finishMovement(); + } else if (key == 'i') { + m_mode = InsertMode; + } else if (key == 'j' || key == Key_Down) { + m_tc.movePosition(Down, KeepAnchor, count()); + finishMovement(); + } else if (key == 'k' || key == Key_Up) { + m_tc.movePosition(Up, KeepAnchor, count()); + finishMovement(); + } else if (key == 'l' || key == Key_Right) { + m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); + finishMovement(); + } else if (key == 'n') { + search(m_lastSearchString, m_lastSearchBackward); + } else if (key == 'N') { + search(m_lastSearchString, !m_lastSearchBackward); + } else if (key == 'p') { + QString text = m_registers[m_register]; + int n = text.count(QChar(ParagraphSeparator)); + if (n > 0) { + m_tc.movePosition(Down); + m_tc.movePosition(StartOfLine); + m_tc.insertText(text); + m_tc.movePosition(Up, MoveAnchor, n); + } else { + m_tc.movePosition(Right); + m_tc.insertText(text); + m_tc.movePosition(Left); + } + } else if (key == control('r')) { + m_editor->redo(); + } else if (key == 'u') { + m_editor->undo(); + } else if (key == 'x') { // = "dl" + if (atEol()) + m_tc.movePosition(Left, MoveAnchor, 1); + m_submode = DeleteSubMode; + m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); + finishMovement(); + } else if (key == 'X') { + if (leftDist() > 0) { + m_tc.movePosition(Left, KeepAnchor, qMin(count(), leftDist())); + m_tc.deleteChar(); + } + finishMovement(); + } else if (key == Key_Backspace) { + m_tc.deletePreviousChar(); + } else { + qDebug() << "Ignored" << key; + } +} + +void FakeVimHandler::Private::handleInsertMode(int key) +{ + if (key == Key_Escape) { + m_mode = CommandMode; + m_tc.movePosition(Left, KeepAnchor, qMin(1, leftDist())); + } else if (key == Key_Left) { + m_tc.movePosition(Left, MoveAnchor, 1); + } else if (key == Key_Down) { + m_tc.movePosition(Down, MoveAnchor, 1); + } else if (key == Key_Up) { + m_tc.movePosition(Up, MoveAnchor, 1); + } else if (key == Key_Right) { + m_tc.movePosition(Right, MoveAnchor, 1); + } else if (key == Key_Return) { + m_tc.insertBlock(); + } else if (key == Key_Backspace) { + m_tc.deletePreviousChar(); + } else { + m_tc.insertText(QChar(key)); + } +} + +void FakeVimHandler::Private::handleExMode(int key) +{ + if (key == Key_Escape) { + m_commandBuffer.clear(); + m_commandCode = 0; + m_mode = CommandMode; + } else if (key == Key_Backspace) { + if (m_commandBuffer.isEmpty()) + m_mode = CommandMode; + else + m_commandBuffer.chop(1); + } else if (key == Key_Return && m_commandCode == ':') { + static QRegExp reGoto("^(\\d+)$"); + if (reGoto.indexIn(m_commandBuffer) != -1) { + int n = reGoto.cap(1).toInt(); + m_tc.setPosition(m_tc.block().document() + ->findBlockByNumber(n - 1).position()); + } else if (m_commandBuffer == "q!" || m_commandBuffer == "q") { + q->quitRequested(m_editor); + } + m_commandBuffer.clear(); + m_mode = CommandMode; + } else if (key == Key_Return + && (m_commandCode == '/' || m_commandCode == '?')) { + m_lastSearchBackward = (m_commandCode == '?'); + m_lastSearchString = m_commandBuffer; + search(m_lastSearchString, m_lastSearchBackward); + m_commandBuffer.clear(); + m_commandCode = 0; + m_mode = CommandMode; + } else { + m_commandBuffer += QChar(key); + } + updateCommandBuffer(); +} + +void FakeVimHandler::Private::search(const QString &needle, bool backwards) +{ + //qDebug() << "NEEDLE " << needle << "BACKWARDS" << backwards; + //int startPos = m_tc.position(); + QTextDocument::FindFlags flags; + if (backwards) + flags = QTextDocument::FindBackward; + + m_tc.movePosition(backwards? Left : Right, MoveAnchor, 1); + m_editor->setTextCursor(m_tc); + if (m_editor->find(needle, flags)) { + m_tc = m_editor->textCursor(); + m_tc.movePosition(Left, MoveAnchor, needle.size()); + return; + } + + int n = 0; + if (backwards) { + QTextBlock block = m_tc.block().document()->lastBlock(); + n = block.position() + block.length() - 1; + } + m_tc.setPosition(n); + m_editor->setTextCursor(m_tc); + if (m_editor->find(needle, flags)) { + m_tc = m_editor->textCursor(); + m_tc.movePosition(Left, MoveAnchor, needle.size()); + if (backwards) + showMessage("search hit TOP, continuing at BOTTOM"); + else + showMessage("search hit BOTTOM, continuing at TOP"); + return; + } + + m_tc.movePosition(backwards ? Right : Left, MoveAnchor, 1); +} + + +/////////////////////////////////////////////////////////////////////// +// +// FakeVimHandler +// +/////////////////////////////////////////////////////////////////////// + +FakeVimHandler::FakeVimHandler(QObject *parent) + : QObject(parent), d(new Private(this)) +{} + +FakeVimHandler::~FakeVimHandler() +{ + delete d; +} + +bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev) +{ + if (ev->type() != QEvent::KeyPress) + return QObject::eventFilter(ob, ev); + return d->eventFilter(ob, ev); +} + diff --git a/src/plugins/fakevim/handler.h b/src/plugins/fakevim/handler.h new file mode 100644 index 00000000000..a1e4431adaa --- /dev/null +++ b/src/plugins/fakevim/handler.h @@ -0,0 +1,70 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ + +#ifndef FAKEVIM_HANDLER_H +#define FAKEVIM_HANDLER_H + +#include + +QT_BEGIN_NAMESPACE +class QString; +class QEvent; +QT_END_NAMESPACE + +namespace FakeVim { +namespace Internal { + +class FakeVimHandler : public QObject +{ + Q_OBJECT + +public: + FakeVimHandler(QObject *parent = 0); + ~FakeVimHandler(); + +signals: + void commandBufferChanged(const QString &); + void quitRequested(QObject *); + +private: + bool eventFilter(QObject *ob, QEvent *ev); + + class Private; + friend class Private; + Private *d; +}; + +} // namespace Internal +} // namespace FakeVim + +#endif // FAKEVIM_H diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 4af2af4195c..bd7cbece15d 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -25,7 +25,8 @@ SUBDIRS = plugin_coreplugin \ # plugin_regexp \ # don't know what to do with this plugin_qtscripteditor \ plugin_cpaster \ - plugin_cmakeprojectmanager + plugin_cmakeprojectmanager \ + plugin_fakevim # These two plugins require private headers from Qt and therefore don't work # with an installed/released version of Qt. @@ -115,6 +116,11 @@ plugin_debugger.depends = plugin_projectexplorer plugin_debugger.depends += plugin_coreplugin plugin_debugger.depends += plugin_cppeditor +plugin_fakevim.subdir = fakevim +plugin_fakevim.depends = plugin_projectexplorer +plugin_fakevim.depends += plugin_coreplugin +plugin_fakevim.depends += plugin_cppeditor + plugin_qtestlib.subdir = qtestlib plugin_qtestlib.depends = plugin_projectexplorer plugin_qtestlib.depends += plugin_coreplugin From 93c60417aa2fb365a5c04fab78723b76376a672e Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 13:03:39 +0100 Subject: [PATCH 016/230] use QTextEdit's "overwriteMode" instead of playing around with the cursor width manually. --- src/plugins/fakevim/fakevimplugin.cpp | 7 ++----- src/plugins/fakevim/fakevimplugin.h | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 72671a37c60..fe283cf862d 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -157,10 +157,7 @@ void FakeVimPlugin::installHandler() return; plainTextEdit->removeEventFilter(m_handler); plainTextEdit->installEventFilter(m_handler); - QFont font = plainTextEdit->font(); - //font.setFamily("Monospace"); - m_savedCursorWidth = plainTextEdit->cursorWidth(); - plainTextEdit->setCursorWidth(QFontMetrics(font).width(QChar('x'))); + plainTextEdit->setOverwriteMode(true); //QMainWindow mw; connect(m_handler, SIGNAL(commandBufferChanged(QString)), @@ -175,7 +172,7 @@ void FakeVimPlugin::removeHandler(QObject *ob) QPlainTextEdit *plainTextEdit = qobject_cast(ob); if (!plainTextEdit) return; - plainTextEdit->setCursorWidth(m_savedCursorWidth); + plainTextEdit->setOverwriteMode(false); } void FakeVimPlugin::showCommandBuffer(const QString &contents) diff --git a/src/plugins/fakevim/fakevimplugin.h b/src/plugins/fakevim/fakevimplugin.h index f31ad1e68e6..d424f0eb66e 100644 --- a/src/plugins/fakevim/fakevimplugin.h +++ b/src/plugins/fakevim/fakevimplugin.h @@ -74,7 +74,6 @@ private: FakeVimHandler *m_handler; ExtensionSystem::PluginManager *m_pm; QAction *m_installHandlerAction; - int m_savedCursorWidth; }; } // namespace Internal From d4f4f508ab8611236325b51380367b17cd0f96d7 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 13:15:57 +0100 Subject: [PATCH 017/230] Handle in insert mode --- src/plugins/fakevim/handler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index fbd59c26b8e..9a827a2ecc5 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -351,6 +351,8 @@ void FakeVimHandler::Private::handleInsertMode(int key) m_tc.insertBlock(); } else if (key == Key_Backspace) { m_tc.deletePreviousChar(); + } else if (key == Key_Tab) { + m_tc.insertText(QChar(9)); } else { m_tc.insertText(QChar(key)); } From 75c9193ff6f6ddf7c6c908c51aa17a41fb4baba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 19 Dec 2008 13:55:03 +0100 Subject: [PATCH 018/230] Use the QKeyEvent::text() for inserting text Avoids inserting all kinds of funny characters when special keys are pressed. For some reason, the Delete key now inserts spades. At least those are more useful than phones, according to hjk. --- src/plugins/fakevim/handler.cpp | 34 +++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 9a827a2ecc5..5c5f89e6699 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -81,11 +81,11 @@ public: static int control(int key) { return key + 256; } void init(); - void handleKey(int key); - void handleInsertMode(int key); - void handleCommandMode(int key); - void handleRegisterMode(int key); - void handleExMode(int key); + void handleKey(int key, const QString &text); + void handleInsertMode(int key, const QString &text); + void handleCommandMode(int key, const QString &text); + void handleRegisterMode(int key, const QString &text); + void handleExMode(int key, const QString &text); void finishMovement(); void updateCommandBuffer(); void search(const QString &needle, bool backwards); @@ -153,7 +153,7 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) key += 32; if ((keyEvent->modifiers() & Qt::ControlModifier) != 0) key += 256; - handleKey(key); + handleKey(key, keyEvent->text()); // We fake vi-style end-of-line behaviour m_fakeEnd = atEol() && m_mode == CommandMode; @@ -176,14 +176,14 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) return true; } -void FakeVimHandler::Private::handleKey(int key) +void FakeVimHandler::Private::handleKey(int key, const QString &text) { if (m_mode == InsertMode) - handleInsertMode(key); + handleInsertMode(key, text); else if (m_mode == CommandMode) - handleCommandMode(key); + handleCommandMode(key, text); else if (m_mode == ExMode) - handleExMode(key); + handleExMode(key, text); } void FakeVimHandler::Private::finishMovement() @@ -218,8 +218,10 @@ void FakeVimHandler::Private::showMessage(const QString &msg) emit q->commandBufferChanged(msg); } -void FakeVimHandler::Private::handleCommandMode(int key) +void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) { + Q_UNUSED(text) + //qDebug() << "-> MODE: " << m_mode << " KEY: " << key; if (m_submode == RegisterSubMode) { m_register = key; @@ -334,7 +336,7 @@ void FakeVimHandler::Private::handleCommandMode(int key) } } -void FakeVimHandler::Private::handleInsertMode(int key) +void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) { if (key == Key_Escape) { m_mode = CommandMode; @@ -351,15 +353,15 @@ void FakeVimHandler::Private::handleInsertMode(int key) m_tc.insertBlock(); } else if (key == Key_Backspace) { m_tc.deletePreviousChar(); - } else if (key == Key_Tab) { - m_tc.insertText(QChar(9)); } else { - m_tc.insertText(QChar(key)); + m_tc.insertText(text); } } -void FakeVimHandler::Private::handleExMode(int key) +void FakeVimHandler::Private::handleExMode(int key, const QString &text) { + Q_UNUSED(text) + if (key == Key_Escape) { m_commandBuffer.clear(); m_commandCode = 0; From af73187d5316853c9c8734d1338e4f3aed2565b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 19 Dec 2008 13:59:45 +0100 Subject: [PATCH 019/230] Fixed Delete to delete instead of inserting spades --- src/plugins/fakevim/handler.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 5c5f89e6699..b9e36f82740 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -331,6 +331,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key == Key_Backspace) { m_tc.deletePreviousChar(); + } else if (key == Key_Delete) { + m_tc.deleteChar(); } else { qDebug() << "Ignored" << key; } @@ -353,6 +355,8 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) m_tc.insertBlock(); } else if (key == Key_Backspace) { m_tc.deletePreviousChar(); + } else if (key == Key_Delete) { + m_tc.deleteChar(); } else { m_tc.insertText(text); } From 4af0768042e05c6d8197636e84ca275461dc4972 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 14:02:27 +0100 Subject: [PATCH 020/230] restore overwrite mode hack. cursor looks better at the end of a line this way... --- src/plugins/fakevim/fakevimplugin.cpp | 7 +++++-- src/plugins/fakevim/fakevimplugin.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index fe283cf862d..72671a37c60 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -157,7 +157,10 @@ void FakeVimPlugin::installHandler() return; plainTextEdit->removeEventFilter(m_handler); plainTextEdit->installEventFilter(m_handler); - plainTextEdit->setOverwriteMode(true); + QFont font = plainTextEdit->font(); + //font.setFamily("Monospace"); + m_savedCursorWidth = plainTextEdit->cursorWidth(); + plainTextEdit->setCursorWidth(QFontMetrics(font).width(QChar('x'))); //QMainWindow mw; connect(m_handler, SIGNAL(commandBufferChanged(QString)), @@ -172,7 +175,7 @@ void FakeVimPlugin::removeHandler(QObject *ob) QPlainTextEdit *plainTextEdit = qobject_cast(ob); if (!plainTextEdit) return; - plainTextEdit->setOverwriteMode(false); + plainTextEdit->setCursorWidth(m_savedCursorWidth); } void FakeVimPlugin::showCommandBuffer(const QString &contents) diff --git a/src/plugins/fakevim/fakevimplugin.h b/src/plugins/fakevim/fakevimplugin.h index d424f0eb66e..f31ad1e68e6 100644 --- a/src/plugins/fakevim/fakevimplugin.h +++ b/src/plugins/fakevim/fakevimplugin.h @@ -74,6 +74,7 @@ private: FakeVimHandler *m_handler; ExtensionSystem::PluginManager *m_pm; QAction *m_installHandlerAction; + int m_savedCursorWidth; }; } // namespace Internal From ccfe1717993de9dd5b69791bc45d9e46961fef75 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 14:35:57 +0100 Subject: [PATCH 021/230] implement 'H' fakevim movement --- src/plugins/fakevim/handler.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index b9e36f82740..ed92a3297b2 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -95,6 +95,7 @@ public: int leftDist() const { return m_tc.position() - m_tc.block().position(); } int rightDist() const { return m_tc.block().length() - leftDist() - 1; } bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; } + void moveToFirstNonBlankOnLine(); FakeVimHandler *q; Mode m_mode; @@ -285,6 +286,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) ++n; m_tc.movePosition(Left, KeepAnchor, n); finishMovement(); + } else if (key == 'H') { + int firstPos = m_editor->cursorForPosition(QPoint(0, 0)).position(); + m_tc.setPosition(firstPos, KeepAnchor); + m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0)); + moveToFirstNonBlankOnLine(); + finishMovement(); } else if (key == 'i') { m_mode = InsertMode; } else if (key == 'j' || key == Key_Down) { @@ -436,6 +443,18 @@ void FakeVimHandler::Private::search(const QString &needle, bool backwards) m_tc.movePosition(backwards ? Right : Left, MoveAnchor, 1); } +void FakeVimHandler::Private::moveToFirstNonBlankOnLine() +{ + QTextBlock block = m_tc.block(); + QTextDocument *doc = m_tc.document(); + int firstPos = m_tc.position(); + for (int i = firstPos, n = firstPos + block.length(); i < n; ++i) { + if (!doc->characterAt(i).isSpace()) { + m_tc.setPosition(i, KeepAnchor); + return; + } + } +} /////////////////////////////////////////////////////////////////////// // From 5107caf24ea18c8be9abee1cbb739e582a541a13 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 14:43:14 +0100 Subject: [PATCH 022/230] implement 'L' in fakevim --- src/plugins/fakevim/handler.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index ed92a3297b2..9a6a08dd8c3 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -303,6 +303,13 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'l' || key == Key_Right) { m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); finishMovement(); + } else if (key == 'L') { + QPoint point = m_editor->geometry().bottomRight(); + int firstPos = m_editor->cursorForPosition(point).position(); + m_tc.setPosition(firstPos, KeepAnchor); + m_tc.movePosition(Up, KeepAnchor, qMax(count(), 1)); + moveToFirstNonBlankOnLine(); + finishMovement(); } else if (key == 'n') { search(m_lastSearchString, m_lastSearchBackward); } else if (key == 'N') { From a01fa6c17b8058884b5ffdce614e911c81d9d299 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 15:00:06 +0100 Subject: [PATCH 023/230] implement 'M' in fakevim --- src/plugins/fakevim/handler.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 9a6a08dd8c3..839ee174825 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -287,8 +287,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(Left, KeepAnchor, n); finishMovement(); } else if (key == 'H') { - int firstPos = m_editor->cursorForPosition(QPoint(0, 0)).position(); - m_tc.setPosition(firstPos, KeepAnchor); + m_tc = m_editor->cursorForPosition(QPoint(0, 0)); m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0)); moveToFirstNonBlankOnLine(); finishMovement(); @@ -304,12 +303,17 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); finishMovement(); } else if (key == 'L') { - QPoint point = m_editor->geometry().bottomRight(); - int firstPos = m_editor->cursorForPosition(point).position(); - m_tc.setPosition(firstPos, KeepAnchor); + int heigth = m_editor->height(); + m_tc = m_editor->cursorForPosition(QPoint(0, heigth)); + m_tc.movePosition(Up, KeepAnchor, qMax(count() - 1, 0)); m_tc.movePosition(Up, KeepAnchor, qMax(count(), 1)); moveToFirstNonBlankOnLine(); finishMovement(); + } else if (key == 'M') { + int heigth = m_editor->height(); + m_tc = m_editor->cursorForPosition(QPoint(0, heigth / 2)); + moveToFirstNonBlankOnLine(); + finishMovement(); } else if (key == 'n') { search(m_lastSearchString, m_lastSearchBackward); } else if (key == 'N') { From 210740c3165107a59e4759a8b19e43213b7a7711 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 15:01:16 +0100 Subject: [PATCH 024/230] fix small glitch in fakevim's 'L' handling --- src/plugins/fakevim/handler.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 839ee174825..ef798dc68f4 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -305,7 +305,6 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'L') { int heigth = m_editor->height(); m_tc = m_editor->cursorForPosition(QPoint(0, heigth)); - m_tc.movePosition(Up, KeepAnchor, qMax(count() - 1, 0)); m_tc.movePosition(Up, KeepAnchor, qMax(count(), 1)); moveToFirstNonBlankOnLine(); finishMovement(); From 02c23836dd9ceb6bf87b66c09ebaf5e0fca2c744 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 15:02:09 +0100 Subject: [PATCH 025/230] comment out watchhandler debug information --- src/plugins/debugger/watchhandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index a370802b813..25fa770823d 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -1204,13 +1204,13 @@ void WatchHandler::loadWatchers() QVariant value; sessionValueRequested("Watchers", &value); m_watchers = value.toStringList(); - qDebug() << "LOAD WATCHERS: " << m_watchers; + //qDebug() << "LOAD WATCHERS: " << m_watchers; reinitializeWatchersHelper(); } void WatchHandler::saveWatchers() { - qDebug() << "SAVE WATCHERS: " << m_watchers; + //qDebug() << "SAVE WATCHERS: " << m_watchers; setSessionValueRequested("Watchers", m_watchers); } From cb7bb2eefe664ffd7e8c4da76fb14599428b9497 Mon Sep 17 00:00:00 2001 From: goro Date: Fri, 19 Dec 2008 15:32:21 +0100 Subject: [PATCH 026/230] PathChooser migration for Qt version config page --- src/libs/utils/pathchooser.cpp | 6 +- src/libs/utils/pathchooser.h | 1 + .../qt4projectmanager/qtversionmanager.cpp | 82 +++++++++---------- .../qt4projectmanager/qtversionmanager.h | 5 +- .../qt4projectmanager/qtversionmanager.ui | 58 ++++--------- 5 files changed, 62 insertions(+), 90 deletions(-) diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index d3743509709..26fa60294ec 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -167,13 +167,15 @@ void PathChooser::slotBrowse() ; } - // TODO make cross-platform - // Delete trailing slashes unless it is "/", only + // Delete trailing slashes unless it is "/"|"\\", only if (!newPath.isEmpty()) { + newPath = QDir::toNativeSeparators(newPath); if (newPath.size() > 1 && newPath.endsWith(QDir::separator())) newPath.truncate(newPath.size() - 1); setPath(newPath); } + + emit browsingFinished(); } bool PathChooser::isValid() const diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index b3898465531..f22c20120b7 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -91,6 +91,7 @@ private: signals: void validChanged(); void changed(); + void browsingFinished(); void returnPressed(); public slots: diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp index f1b9b956021..e39240118d1 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.cpp +++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp @@ -368,6 +368,10 @@ QtDirWidget::QtDirWidget(QWidget *parent, QList versions, int defau , m_specifyPathString(tr("")) { m_ui.setupUi(this); + m_ui.qtPath->setExpectedKind(Core::Utils::PathChooser::Directory); + m_ui.qtPath->setPromptDialogTitle(tr("Select QTDIR")); + m_ui.mingwPath->setExpectedKind(Core::Utils::PathChooser::Directory); + m_ui.qtPath->setPromptDialogTitle(tr("Select MinGW Directory")); m_ui.addButton->setIcon(QIcon(Core::Constants::ICON_PLUS)); m_ui.delButton->setIcon(QIcon(Core::Constants::ICON_MINUS)); @@ -385,19 +389,22 @@ QtDirWidget::QtDirWidget(QWidget *parent, QList versions, int defau connect(m_ui.nameEdit, SIGNAL(textEdited(const QString &)), this, SLOT(updateCurrentQtName())); - connect(m_ui.pathEdit, SIGNAL(textEdited(const QString &)), + + + connect(m_ui.qtPath, SIGNAL(changed()), this, SLOT(updateCurrentQtPath())); - connect(m_ui.mingwLineEdit, SIGNAL(textEdited(const QString &)), + connect(m_ui.mingwPath, SIGNAL(changed()), this, SLOT(updateCurrentMingwDirectory())); connect(m_ui.addButton, SIGNAL(clicked()), this, SLOT(addQtDir())); connect(m_ui.delButton, SIGNAL(clicked()), this, SLOT(removeQtDir())); - connect(m_ui.browseButton, SIGNAL(clicked()), - this, SLOT(browse())); - connect(m_ui.mingwBrowseButton, SIGNAL(clicked()), - this, SLOT(mingwBrowse())); + + connect(m_ui.qtPath, SIGNAL(browsingFinished()), + this, SLOT(onQtBrowsed())); + connect(m_ui.mingwPath, SIGNAL(browsingFinished()), + this, SLOT(onMingwBrowsed())); connect(m_ui.qtdirList, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(versionChanged(QTreeWidgetItem *, QTreeWidgetItem *))); @@ -421,11 +428,11 @@ void QtDirWidget::addQtDir() item->setText(1, newVersion->path()); item->setData(0, Qt::UserRole, newVersion->uniqueId()); - m_ui.nameEdit->setText(newVersion->name()); - m_ui.pathEdit->setText(newVersion->path()); - - m_ui.defaultCombo->addItem(newVersion->name()); m_ui.qtdirList->setCurrentItem(item); + + m_ui.nameEdit->setText(newVersion->name()); + m_ui.qtPath->setPath(newVersion->path()); + m_ui.defaultCombo->addItem(newVersion->name()); m_ui.nameEdit->setFocus(); m_ui.nameEdit->selectAll(); } @@ -459,10 +466,14 @@ void QtDirWidget::updateState() && m_versions.at(m_ui.qtdirList->indexOfTopLevelItem(m_ui.qtdirList->currentItem()))->isSystemVersion()); m_ui.delButton->setEnabled(enabled && !isSystemVersion); m_ui.nameEdit->setEnabled(enabled && !isSystemVersion); - m_ui.pathEdit->setEnabled(enabled && !isSystemVersion); - m_ui.browseButton->setEnabled(enabled && !isSystemVersion); - m_ui.mingwBrowseButton->setEnabled(enabled); - m_ui.mingwLineEdit->setEnabled(enabled); + m_ui.qtPath->setEnabled(enabled && !isSystemVersion); + m_ui.mingwPath->setEnabled(enabled); +} + +void QtDirWidget::makeMingwVisible(bool visible) +{ + m_ui.mingwLabel->setVisible(visible); + m_ui.mingwPath->setVisible(visible); } void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item) @@ -475,16 +486,12 @@ void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item) if (t == QtVersion::MinGW) { m_ui.msvcComboBox->setVisible(false); m_ui.msvcLabel->setVisible(false); - m_ui.mingwLineEdit->setVisible(true); - m_ui.mingwLabel->setVisible(true); - m_ui.mingwBrowseButton->setVisible(true); - m_ui.mingwLineEdit->setText(m_versions.at(index)->mingwDirectory()); + makeMingwVisible(true); + m_ui.mingwPath->setPath(m_versions.at(index)->mingwDirectory()); } else if (t == QtVersion::MSVC || t == QtVersion::WINCE){ m_ui.msvcComboBox->setVisible(false); m_ui.msvcLabel->setVisible(true); - m_ui.mingwLineEdit->setVisible(false); - m_ui.mingwLabel->setVisible(false); - m_ui.mingwBrowseButton->setVisible(false); + makeMingwVisible(false); QList msvcenvironments = MSVCEnvironment::availableVersions(); if (msvcenvironments.count() == 0) { m_ui.msvcLabel->setText(tr("No Visual Studio Installation found")); @@ -506,9 +513,7 @@ void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item) } else if (t == QtVersion::INVALID) { m_ui.msvcComboBox->setVisible(false); m_ui.msvcLabel->setVisible(false); - m_ui.mingwLineEdit->setVisible(false); - m_ui.mingwLabel->setVisible(false); - m_ui.mingwBrowseButton->setVisible(false); + makeMingwVisible(false); if (!m_versions.at(index)->isInstalled()) m_ui.errorLabel->setText(tr("The Qt Version is not installed. Run make install") .arg(m_versions.at(index)->path())); @@ -517,9 +522,7 @@ void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item) } else { //QtVersion::Other m_ui.msvcComboBox->setVisible(false); m_ui.msvcLabel->setVisible(false); - m_ui.mingwLineEdit->setVisible(false); - m_ui.mingwLabel->setVisible(false); - m_ui.mingwBrowseButton->setVisible(false); + makeMingwVisible(false); m_ui.errorLabel->setText("Found Qt version " + m_versions.at(index)->qtVersionString() + " using mkspec " @@ -528,9 +531,7 @@ void QtDirWidget::showEnvironmentPage(QTreeWidgetItem *item) } else { m_ui.msvcComboBox->setVisible(false); m_ui.msvcLabel->setVisible(false); - m_ui.mingwLineEdit->setVisible(false); - m_ui.mingwLabel->setVisible(false); - m_ui.mingwBrowseButton->setVisible(false); + makeMingwVisible(false); } } @@ -541,24 +542,21 @@ void QtDirWidget::versionChanged(QTreeWidgetItem *item, QTreeWidgetItem *old) } if (item) { m_ui.nameEdit->setText(item->text(0)); - m_ui.pathEdit->setText(item->text(1)); + m_ui.qtPath->setPath(item->text(1)); } else { m_ui.nameEdit->clear(); - m_ui.pathEdit->clear(); + m_ui.qtPath->setPath(""); // clear() } showEnvironmentPage(item); updateState(); } -void QtDirWidget::browse() +void QtDirWidget::onQtBrowsed() { - QString dir = QFileDialog::getExistingDirectory(this, tr("Select QTDIR")); - + const QString dir = m_ui.qtPath->path(); if (dir.isEmpty()) return; - dir = QDir::toNativeSeparators(dir); - m_ui.pathEdit->setText(dir); updateCurrentQtPath(); if (m_ui.nameEdit->text().isEmpty() || m_ui.nameEdit->text() == m_specifyNameString) { QStringList dirSegments = dir.split(QDir::separator(), QString::SkipEmptyParts); @@ -569,14 +567,12 @@ void QtDirWidget::browse() updateState(); } -void QtDirWidget::mingwBrowse() +void QtDirWidget::onMingwBrowsed() { - QString dir = QFileDialog::getExistingDirectory(this, tr("Select MinGW Directory")); + const QString dir = m_ui.mingwPath->path(); if (dir.isEmpty()) return; - dir = QDir::toNativeSeparators(dir); - m_ui.mingwLineEdit->setText(dir); updateCurrentMingwDirectory(); updateState(); } @@ -647,7 +643,7 @@ void QtDirWidget::updateCurrentQtPath() QTreeWidgetItem *currentItem = m_ui.qtdirList->currentItem(); Q_ASSERT(currentItem); int currentItemIndex = m_ui.qtdirList->indexOfTopLevelItem(currentItem); - m_versions[currentItemIndex]->setPath(m_ui.pathEdit->text()); + m_versions[currentItemIndex]->setPath(m_ui.qtPath->path()); currentItem->setText(1, m_versions[currentItemIndex]->path()); showEnvironmentPage(currentItem); @@ -658,7 +654,7 @@ void QtDirWidget::updateCurrentMingwDirectory() QTreeWidgetItem *currentItem = m_ui.qtdirList->currentItem(); Q_ASSERT(currentItem); int currentItemIndex = m_ui.qtdirList->indexOfTopLevelItem(currentItem); - m_versions[currentItemIndex]->setMingwDirectory(m_ui.mingwLineEdit->text()); + m_versions[currentItemIndex]->setMingwDirectory(m_ui.mingwPath->path()); } void QtDirWidget::msvcVersionChanged() diff --git a/src/plugins/qt4projectmanager/qtversionmanager.h b/src/plugins/qt4projectmanager/qtversionmanager.h index 164e40c6d8e..a76a62ada04 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.h +++ b/src/plugins/qt4projectmanager/qtversionmanager.h @@ -149,8 +149,9 @@ private slots: void addQtDir(); void removeQtDir(); void updateState(); - void browse(); - void mingwBrowse(); + void makeMingwVisible(bool visible); + void onQtBrowsed(); + void onMingwBrowsed(); void defaultChanged(int index); void updateCurrentQtName(); void updateCurrentQtPath(); diff --git a/src/plugins/qt4projectmanager/qtversionmanager.ui b/src/plugins/qt4projectmanager/qtversionmanager.ui index de93505cb09..0d3941d0388 100644 --- a/src/plugins/qt4projectmanager/qtversionmanager.ui +++ b/src/plugins/qt4projectmanager/qtversionmanager.ui @@ -109,16 +109,6 @@ - - - - - - - ... - - - @@ -126,16 +116,6 @@ - - - - - - - ... - - - @@ -153,6 +133,12 @@ + + + + + + @@ -179,34 +165,20 @@ + + + Core::Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 +
+
qtdirList delButton nameEdit - pathEdit defaultCombo - browseButton - - - - - - - - - - - - - - - - - - - - - + From 4c1502334cb5652104576747acefff84f6f14c2a Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 19 Dec 2008 16:20:39 +0100 Subject: [PATCH 027/230] handle 'z' in fakevim --- src/plugins/fakevim/handler.cpp | 61 ++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index ef798dc68f4..8c213c34c8e 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -33,16 +33,18 @@ #include "handler.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include using namespace FakeVim::Internal; @@ -66,9 +68,21 @@ const int ParagraphSeparator = 0x00002029; using namespace Qt; -enum Mode { InsertMode, CommandMode, ExMode }; +enum Mode +{ + InsertMode, + CommandMode, + ExMode +}; -enum SubMode { NoSubMode, RegisterSubMode, ChangeSubMode, DeleteSubMode }; +enum SubMode +{ + NoSubMode, + RegisterSubMode, + ChangeSubMode, + DeleteSubMode, + ZSubMode +}; class FakeVimHandler::Private { @@ -95,6 +109,7 @@ public: int leftDist() const { return m_tc.position() - m_tc.block().position(); } int rightDist() const { return m_tc.block().length() - leftDist() - 1; } bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; } + void moveToFirstNonBlankOnLine(); FakeVimHandler *q; @@ -237,6 +252,23 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(Down, KeepAnchor, count()); m_registers[m_register] = m_tc.selectedText(); finishMovement(); + } else if (m_submode == ZSubMode) { + if (key == Key_Return) { + // cursor line to top of window, cursor on first non-blank + QRect rect = m_editor->cursorRect(); + int blocksUp = rect.y() / rect.height(); + int blockNumber = m_tc.block().blockNumber(); + QScrollBar *scrollBar = m_editor->verticalScrollBar(); + if (blockNumber != blocksUp) { + scrollBar->setValue(scrollBar->value() * blockNumber + / (blockNumber - blocksUp)); + } + moveToFirstNonBlankOnLine(); + finishMovement(); + } else { + qDebug() << "Ignored z + " << key << text; + } + m_submode = NoSubMode; } else if (key >= '0' && key <= '9') { if (key == '0' && m_count.isEmpty()) { m_tc.movePosition(StartOfLine, KeepAnchor); @@ -346,12 +378,14 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.deleteChar(); } finishMovement(); + } else if (key == 'z') { + m_submode = ZSubMode; } else if (key == Key_Backspace) { m_tc.deletePreviousChar(); } else if (key == Key_Delete) { m_tc.deleteChar(); } else { - qDebug() << "Ignored" << key; + qDebug() << "Ignored" << key << text; } } @@ -457,6 +491,7 @@ void FakeVimHandler::Private::moveToFirstNonBlankOnLine() { QTextBlock block = m_tc.block(); QTextDocument *doc = m_tc.document(); + m_tc.movePosition(StartOfLine); int firstPos = m_tc.position(); for (int i = firstPos, n = firstPos + block.length(); i < n; ++i) { if (!doc->characterAt(i).isSpace()) { From 12bcc11389ff7946615ea306dd9a70c7eebbf8bc Mon Sep 17 00:00:00 2001 From: goro Date: Fri, 19 Dec 2008 16:39:02 +0100 Subject: [PATCH 028/230] PathChooser migration for external app debug lanuching --- src/libs/utils/pathchooser.cpp | 3 +- src/plugins/debugger/startexternaldialog.cpp | 16 ++--- src/plugins/debugger/startexternaldialog.h | 3 - src/plugins/debugger/startexternaldialog.ui | 74 ++++++++++---------- 4 files changed, 43 insertions(+), 53 deletions(-) diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index 26fa60294ec..b769ea75589 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -138,8 +138,7 @@ QString PathChooser::path() const void PathChooser::setPath(const QString &path) { - const QString defaultPath = path.isEmpty() ? homePath() : path; - m_d->m_lineEdit->setText(QDir::toNativeSeparators(defaultPath)); + m_d->m_lineEdit->setText(QDir::toNativeSeparators(path)); } void PathChooser::slotBrowse() diff --git a/src/plugins/debugger/startexternaldialog.cpp b/src/plugins/debugger/startexternaldialog.cpp index b8a5a59691f..ba88f5f74c2 100644 --- a/src/plugins/debugger/startexternaldialog.cpp +++ b/src/plugins/debugger/startexternaldialog.cpp @@ -42,6 +42,8 @@ StartExternalDialog::StartExternalDialog(QWidget *parent) : QDialog(parent) { setupUi(this); + execFile->setExpectedKind(Core::Utils::PathChooser::File); + execFile->setPromptDialogTitle(tr("Select Executable")); buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); //execLabel->setHidden(false); @@ -53,14 +55,11 @@ StartExternalDialog::StartExternalDialog(QWidget *parent) connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); - - connect(browseButton, SIGNAL(clicked()), - this, SLOT(onBrowseButton())); } void StartExternalDialog::setExecutableFile(const QString &str) { - execEdit->setText(str); + execFile->setPath(str); } void StartExternalDialog::setExecutableArguments(const QString &str) @@ -70,7 +69,7 @@ void StartExternalDialog::setExecutableArguments(const QString &str) QString StartExternalDialog::executableFile() const { - return execEdit->text(); + return execFile->path(); } QString StartExternalDialog::executableArguments() const @@ -116,10 +115,3 @@ QString StartExternalDialog::executableArguments() const return result; */ } - -void StartExternalDialog::onBrowseButton() -{ - QString fileName = QFileDialog::getOpenFileName(this, tr("Select Executable"), - execEdit->text()); - execEdit->setText(fileName); -} diff --git a/src/plugins/debugger/startexternaldialog.h b/src/plugins/debugger/startexternaldialog.h index 3cfe4c54206..0707252774d 100644 --- a/src/plugins/debugger/startexternaldialog.h +++ b/src/plugins/debugger/startexternaldialog.h @@ -53,9 +53,6 @@ public: QString executableFile() const; QString executableArguments() const; - -private slots: - void onBrowseButton(); }; } // namespace Debugger diff --git a/src/plugins/debugger/startexternaldialog.ui b/src/plugins/debugger/startexternaldialog.ui index 7888db2a3e6..1b93356584c 100644 --- a/src/plugins/debugger/startexternaldialog.ui +++ b/src/plugins/debugger/startexternaldialog.ui @@ -1,7 +1,8 @@ - + + StartExternalDialog - - + + 0 0 @@ -9,59 +10,52 @@ 127 - + Start Debugger - - + + 6 - + 9 - - + + 0 - + 6 - - - - - - - - - + + + Executable: - - - - ... - - - - - - + + + Arguments: + + + + + + - + Qt::Vertical - + 407 16 @@ -70,24 +64,32 @@ - - + + Qt::Horizontal - - + + Qt::Horizontal - + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + Core::Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 +
+
From defc270896bfc852faa7cad19b154a314b2661e7 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 19 Dec 2008 17:42:08 +0100 Subject: [PATCH 029/230] Fixes: Start a git branch dialog. --- src/plugins/git/branchdialog.cpp | 174 +++++++++++++++++++++++++++++++ src/plugins/git/branchdialog.h | 60 +++++++++++ src/plugins/git/branchdialog.ui | 95 +++++++++++++++++ src/plugins/git/branchmodel.cpp | 136 ++++++++++++++++++++++++ src/plugins/git/branchmodel.h | 58 +++++++++++ src/plugins/git/git.pro | 14 +-- src/plugins/git/gitclient.cpp | 42 ++++++++ src/plugins/git/gitclient.h | 6 ++ src/plugins/git/gitplugin.cpp | 21 +++- 9 files changed, 596 insertions(+), 10 deletions(-) create mode 100644 src/plugins/git/branchdialog.cpp create mode 100644 src/plugins/git/branchdialog.h create mode 100644 src/plugins/git/branchdialog.ui create mode 100644 src/plugins/git/branchmodel.cpp create mode 100644 src/plugins/git/branchmodel.h diff --git a/src/plugins/git/branchdialog.cpp b/src/plugins/git/branchdialog.cpp new file mode 100644 index 00000000000..0918f2d6c07 --- /dev/null +++ b/src/plugins/git/branchdialog.cpp @@ -0,0 +1,174 @@ +#include "branchdialog.h" +#include "branchmodel.h" +#include "gitclient.h" +#include "ui_branchdialog.h" + +#include +#include +#include + +// Single selection helper +static inline int selectedRow(const QAbstractItemView *listView) +{ + const QModelIndexList indexList = listView->selectionModel()->selectedIndexes(); + if (indexList.size() == 1) + return indexList.front().row(); + return -1; +} + +namespace Git { + namespace Internal { + +BranchDialog::BranchDialog(QWidget *parent) : + QDialog(parent), + m_client(0), + m_ui(new Ui::BranchDialog), + m_checkoutButton(0), + m_deleteButton(0), + m_localModel(0), + m_remoteModel(0) +{ + m_ui->setupUi(this); + m_checkoutButton = m_ui->buttonBox->addButton(tr("Checkout"), QDialogButtonBox::AcceptRole); + connect(m_checkoutButton, SIGNAL(clicked()), this, SLOT(slotCheckoutSelectedBranch())); + + m_deleteButton = m_ui->buttonBox->addButton(tr("Delete"), QDialogButtonBox::ActionRole); + connect(m_deleteButton, SIGNAL(clicked()), this, SLOT(slotDeleteSelectedBranch())); + + connect(m_ui->localBranchListView, SIGNAL(doubleClicked(QModelIndex)), this, + SLOT(slotLocalBranchActivated())); +} + +BranchDialog::~BranchDialog() +{ + delete m_ui; +} + +bool BranchDialog::init(GitClient *client, const QString &workingDirectory, QString *errorMessage) +{ + // Find repository and populate models. + m_client = client; + m_repoDirectory = GitClient::findRepositoryForDirectory(workingDirectory); + if (m_repoDirectory.isEmpty()) { + *errorMessage = tr("Unable to find the repository directory for '%1'.").arg(workingDirectory); + return false; + } + m_ui->repositoryFieldLabel->setText(m_repoDirectory); + + m_localModel = new BranchModel(client, BranchModel::LocalBranches, this); + m_remoteModel = new BranchModel(client, BranchModel::RemoteBranches, this); + if (!m_localModel->refresh(workingDirectory, errorMessage) + || !m_remoteModel->refresh(workingDirectory, errorMessage)) + return false; + + m_ui->localBranchListView->setModel(m_localModel); + m_ui->remoteBranchListView->setModel(m_remoteModel); + // Selection model comes into existence only now + connect(m_ui->localBranchListView->selectionModel(), + SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(slotEnableButtons())); + connect(m_ui->remoteBranchListView->selectionModel(), + SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + this, SLOT(slotEnableButtons())); + slotEnableButtons(); + return true; +} + +int BranchDialog::selectedLocalBranchIndex() const +{ + return selectedRow(m_ui->localBranchListView); +} + +int BranchDialog::selectedRemoteBranchIndex() const +{ + return selectedRow(m_ui->remoteBranchListView); +} + +void BranchDialog::slotEnableButtons() +{ + // We can switch to or delete branches that are not current. + const int selectedLocalRow = selectedLocalBranchIndex(); + const int currentLocalBranch = m_localModel->currentBranch(); + + const bool hasSelection = selectedLocalRow != -1; + const bool currentIsNotSelected = hasSelection && selectedLocalRow != currentLocalBranch; + + m_checkoutButton->setEnabled(currentIsNotSelected); + m_deleteButton->setEnabled(currentIsNotSelected); +} + +bool BranchDialog::ask(const QString &title, const QString &what, bool defaultButton) +{ + return QMessageBox::question(this, title, what, QMessageBox::Yes|QMessageBox::No, + defaultButton ? QMessageBox::Yes : QMessageBox::No) == QMessageBox::Yes; +} + +/* Prompt to delete a local branch and do so. */ +void BranchDialog::slotDeleteSelectedBranch() +{ + const int idx = selectedLocalBranchIndex(); + if (idx == -1) + return; + const QString name = m_localModel->branchName(idx); + if (!ask(tr("Delete Branch"), tr("Would you like to delete the branch '%1'?").arg(name), true)) + return; + QString errorMessage; + bool ok = false; + do { + QString output; + QStringList args(QLatin1String("-D")); + args << name; + if (!m_client->synchronousBranchCmd(m_repoDirectory, args, &output, &errorMessage)) + break; + if (!m_localModel->refresh(m_repoDirectory, &errorMessage)) + break; + ok = true; + } while (false); + slotEnableButtons(); + if (!ok) + QMessageBox::warning(this, tr("Failed to delete branch"), errorMessage); +} + +void BranchDialog::slotLocalBranchActivated() +{ + if (m_checkoutButton->isEnabled()) + m_checkoutButton->animateClick(); +} + +/* Ask to stash away changes and then close dialog and do an asynchronous + * checkout. */ +void BranchDialog::slotCheckoutSelectedBranch() +{ + const int idx = selectedLocalBranchIndex(); + if (idx == -1) + return; + const QString name = m_localModel->branchName(idx); + QString errorMessage; + switch (m_client->ensureStash(m_repoDirectory, &errorMessage)) { + case GitClient::StashUnchanged: + case GitClient::Stashed: + case GitClient::NotStashed: + break; + case GitClient::StashCanceled: + return; + case GitClient::StashFailed: + QMessageBox::warning(this, tr("Failed to stash"), errorMessage); + return; + } + accept(); + m_client->checkoutBranch(m_repoDirectory, name); +} + +void BranchDialog::changeEvent(QEvent *e) +{ + switch (e->type()) { + case QEvent::LanguageChange: + m_ui->retranslateUi(this); + break; + default: + break; + } +} + +} // namespace Internal +} // namespace Git diff --git a/src/plugins/git/branchdialog.h b/src/plugins/git/branchdialog.h new file mode 100644 index 00000000000..064719b8ff0 --- /dev/null +++ b/src/plugins/git/branchdialog.h @@ -0,0 +1,60 @@ +#ifndef BRANCHDIALOG_H +#define BRANCHDIALOG_H + +#include + +QT_BEGIN_NAMESPACE +class QPushButton; +QT_END_NAMESPACE + +namespace Git { + namespace Internal { + namespace Ui { + class BranchDialog; + } + + class GitClient; + class BranchModel; + + /* Branch dialog: Display a list of local branches at the top + * and remote branches below. Offers to checkout/delete local + * branches. + * TODO: Add new branch (optionally tracking a remote one). + * How to find out that a local branch is a tracking one? */ + class BranchDialog : public QDialog { + Q_OBJECT + Q_DISABLE_COPY(BranchDialog) + public: + explicit BranchDialog(QWidget *parent = 0); + + bool init(GitClient *client, const QString &workingDirectory, QString *errorMessage); + + virtual ~BranchDialog(); + + protected: + virtual void changeEvent(QEvent *e); + + private slots: + void slotEnableButtons(); + void slotCheckoutSelectedBranch(); + void slotDeleteSelectedBranch(); + void slotLocalBranchActivated(); + + private: + bool ask(const QString &title, const QString &what, bool defaultButton); + + int selectedLocalBranchIndex() const; + int selectedRemoteBranchIndex() const; + + GitClient *m_client; + Ui::BranchDialog *m_ui; + QPushButton *m_checkoutButton; + QPushButton *m_deleteButton; + + BranchModel *m_localModel; + BranchModel *m_remoteModel; + QString m_repoDirectory; + }; + } // namespace Internal +} // namespace Git +#endif // BRANCHDIALOG_H diff --git a/src/plugins/git/branchdialog.ui b/src/plugins/git/branchdialog.ui new file mode 100644 index 00000000000..07f7ff656b1 --- /dev/null +++ b/src/plugins/git/branchdialog.ui @@ -0,0 +1,95 @@ + + + Git::Internal::BranchDialog + + + + 0 + 0 + 544 + 631 + + + + Branches + + + + + + General information + + + + + + Repository: + + + + + + + TextLabel + + + + + + + + + + Branches + + + + + + + + + + + + Remote branches + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + rejected() + Git::Internal::BranchDialog + reject() + + + 466 + 614 + + + 544 + 23 + + + + + diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp new file mode 100644 index 00000000000..0881aea654b --- /dev/null +++ b/src/plugins/git/branchmodel.cpp @@ -0,0 +1,136 @@ +#include "branchmodel.h" +#include "gitclient.h" + +#include + +enum { debug = 0 }; + +namespace Git { + namespace Internal { + +// Parse a branch line: " *name sha description". Return true if it is +// the current one +bool BranchModel::Branch::parse(const QString &lineIn, bool *isCurrent) +{ + if (debug) + qDebug() << Q_FUNC_INFO << lineIn; + + *isCurrent = lineIn.startsWith(QLatin1String("* ")); + if (lineIn.size() < 3) + return false; + + const QStringList tokens =lineIn.mid(2).split(QLatin1Char(' '), QString::SkipEmptyParts); + if (tokens.size() < 2) + return false; + name = tokens.at(0); + currentSHA= tokens.at(1); + toolTip.clear(); + return true; +} + +static inline Qt::ItemFlags typeToModelFlags(BranchModel::Type t) +{ + Qt::ItemFlags rc = Qt::ItemIsSelectable|Qt::ItemIsEnabled; + if (t == BranchModel::BranchModel::LocalBranches) + rc |= Qt::ItemIsUserCheckable; + return rc; +} + +// --- BranchModel +BranchModel::BranchModel(GitClient *client, Type type, QObject *parent) : + QAbstractListModel(parent), + m_type(type), + m_flags(typeToModelFlags(type)), + m_client(client), + m_currentBranch(-1) +{ +} + +int BranchModel::currentBranch() const +{ + return m_currentBranch; +} + +QString BranchModel::branchName(int row) const +{ + return m_branches.at(row).name; +} + +int BranchModel::rowCount(const QModelIndex & /* parent */) const +{ + return m_branches.size(); +} + +QVariant BranchModel::data(const QModelIndex &index, int role) const +{ + const int row = index.row(); + switch (role) { + case Qt::DisplayRole: + return branchName(row); + case Qt::ToolTipRole: + if (m_branches.at(row).toolTip.isEmpty()) + m_branches.at(row).toolTip = toolTip(m_branches.at(row).currentSHA); + return m_branches.at(row).toolTip; + break; + case Qt::CheckStateRole: + if (m_type == RemoteBranches) + return QVariant(); + return row == m_currentBranch ? Qt::Checked : Qt::Unchecked; + default: + break; + } + return QVariant(); +} + +Qt::ItemFlags BranchModel::flags(const QModelIndex & /*index */) const +{ + return m_flags; +} + +bool BranchModel::refresh(const QString &workingDirectory, QString *errorMessage) +{ + // Run branch command with verbose. + QStringList branchArgs(QLatin1String("-v")); + QString output; + if (m_type == RemoteBranches) + branchArgs.push_back(QLatin1String("-r")); + if (!m_client->synchronousBranchCmd(workingDirectory, branchArgs, &output, errorMessage)) + return false; + if (debug) + qDebug() << Q_FUNC_INFO << workingDirectory << output; + // Parse output + m_workingDirectory = workingDirectory; + m_branches.clear(); + m_currentBranch = -1; + const QStringList branches = output.split(QLatin1Char('\n')); + const int branchCount = branches.size(); + bool isCurrent; + for (int b = 0; b < branchCount; b++) { + Branch newBranch; + if (newBranch.parse(branches.at(b), &isCurrent)) { + m_branches.push_back(newBranch); + if (isCurrent) + m_currentBranch = b; + } + } + reset(); + return true; +} + +QString BranchModel::toolTip(const QString &sha) const +{ + // Show the sha description excluding diff as toolTip + QString output; + QString errorMessage; + if (!m_client->synchronousShow(m_workingDirectory, sha, &output, &errorMessage)) + return errorMessage; + // Remove 'diff' output + const int diffPos = output.indexOf(QLatin1String("\ndiff --")); + if (diffPos != -1) + output.remove(diffPos, output.size() - diffPos); + return output; +} + +} +} + diff --git a/src/plugins/git/branchmodel.h b/src/plugins/git/branchmodel.h new file mode 100644 index 00000000000..5083a1c377c --- /dev/null +++ b/src/plugins/git/branchmodel.h @@ -0,0 +1,58 @@ +#ifndef BRANCHMODEL_H +#define BRANCHMODEL_H + +#include +#include + +namespace Git { + namespace Internal { + +class GitClient; + +/* A model to list git branches in a simple list of branch names. Local + * branches will have a read-only checkbox indicating the current one. The + * [delayed] tooltip describes the latest commit. */ + +class BranchModel : public QAbstractListModel { +public: + enum Type { LocalBranches, RemoteBranches }; + + explicit BranchModel(GitClient *client, + Type type = LocalBranches, + QObject *parent = 0); + + bool refresh(const QString &workingDirectory, QString *errorMessage); + + int currentBranch() const; + QString branchName(int row) const; + + // QAbstractListModel + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + +private: + QString toolTip(const QString &sha) const; + + struct Branch { + bool parse(const QString &line, bool *isCurrent); + + QString name; + QString currentSHA; + mutable QString toolTip; + }; + typedef QList BranchList; + + const Type m_type; + const Qt::ItemFlags m_flags; + GitClient *m_client; + + QString m_workingDirectory; + BranchList m_branches; + int m_currentBranch; +}; + +} +} + +#endif // BRANCHMODEL_H diff --git a/src/plugins/git/git.pro b/src/plugins/git/git.pro index 3c4ca176cb5..7f4ed2fc0cc 100644 --- a/src/plugins/git/git.pro +++ b/src/plugins/git/git.pro @@ -6,7 +6,6 @@ include(../../plugins/texteditor/texteditor.pri) include(../../plugins/coreplugin/coreplugin.pri) include(../../plugins/vcsbase/vcsbase.pri) include(../../libs/utils/utils.pri) - HEADERS += gitplugin.h \ gitconstants.h \ gitoutputwindow.h \ @@ -19,8 +18,9 @@ HEADERS += gitplugin.h \ gitsubmiteditorwidget.h \ gitsubmiteditor.h \ gitversioncontrol.h \ - gitsettings.h - + gitsettings.h \ + branchdialog.h \ + branchmodel.h SOURCES += gitplugin.cpp \ gitoutputwindow.cpp \ gitclient.cpp \ @@ -32,8 +32,10 @@ SOURCES += gitplugin.cpp \ gitsubmiteditorwidget.cpp \ gitsubmiteditor.cpp \ gitversioncontrol.cpp \ - gitsettings.cpp - + gitsettings.cpp \ + branchdialog.cpp \ + branchmodel.cpp FORMS += changeselectiondialog.ui \ settingspage.ui \ - gitsubmitpanel.ui + gitsubmitpanel.ui \ + branchdialog.ui diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 83dafdc1b66..f3d507171d2 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -276,6 +276,13 @@ void GitClient::blame(const QString &workingDirectory, const QString &fileName) executeGit(workingDirectory, arguments, editor); } +void GitClient::checkoutBranch(const QString &workingDirectory, const QString &branch) +{ + QStringList arguments(QLatin1String("checkout")); + arguments << branch; + executeGit(workingDirectory, arguments, 0, true); +} + void GitClient::checkout(const QString &workingDirectory, const QString &fileName) { // Passing an empty argument as the file name is very dangereous, since this makes @@ -395,6 +402,41 @@ bool GitClient::synchronousStash(const QString &workingDirectory, QString *error return true; } +bool GitClient::synchronousBranchCmd(const QString &workingDirectory, QStringList branchArgs, + QString *output, QString *errorMessage) +{ + if (Git::Constants::debug) + qDebug() << Q_FUNC_INFO << workingDirectory << branchArgs; + branchArgs.push_front(QLatin1String("branch")); + QByteArray outputText; + QByteArray errorText; + const bool rc = synchronousGit(workingDirectory, branchArgs, &outputText, &errorText); + if (!rc) { + *errorMessage = tr("Unable to run branch command: %1: %2").arg(workingDirectory, QString::fromLocal8Bit(errorText)); + return false; + } + *output = QString::fromLocal8Bit(outputText).remove(QLatin1Char('\r')); + return true; +} + +bool GitClient::synchronousShow(const QString &workingDirectory, const QString &id, + QString *output, QString *errorMessage) +{ + if (Git::Constants::debug) + qDebug() << Q_FUNC_INFO << workingDirectory << id; + QStringList args(QLatin1String("show")); + args << id; + QByteArray outputText; + QByteArray errorText; + const bool rc = synchronousGit(workingDirectory, args, &outputText, &errorText); + if (!rc) { + *errorMessage = tr("Unable to run show: %1: %2").arg(workingDirectory, QString::fromLocal8Bit(errorText)); + return false; + } + *output = QString::fromLocal8Bit(outputText).remove(QLatin1Char('\r')); + return true; +} + void GitClient::executeGit(const QString &workingDirectory, const QStringList &arguments, VCSBase::VCSBaseEditor* editor, diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index af45bbb9a36..f09daa00ab8 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -86,6 +86,7 @@ public: void blame(const QString &workingDirectory, const QString &fileName); void showCommit(const QString &workingDirectory, const QString &commit); void checkout(const QString &workingDirectory, const QString &file); + void checkoutBranch(const QString &workingDirectory, const QString &branch); void hardReset(const QString &workingDirectory, const QString &commit); void addFile(const QString &workingDirectory, const QString &fileName); bool synchronousAdd(const QString &workingDirectory, const QStringList &files); @@ -93,6 +94,11 @@ public: bool synchronousReset(const QString &workingDirectory, const QStringList &files, QString *errorMessage); bool synchronousCheckout(const QString &workingDirectory, const QStringList &files, QString *errorMessage); bool synchronousStash(const QString &workingDirectory, QString *errorMessage); + bool synchronousBranchCmd(const QString &workingDirectory, QStringList branchArgs, + QString *output, QString *errorMessage); + bool synchronousShow(const QString &workingDirectory, const QString &id, + QString *output, QString *errorMessage); + void pull(const QString &workingDirectory); void push(const QString &workingDirectory); diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index 85af681d209..fe2d93adbff 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -40,6 +40,7 @@ #include "giteditor.h" #include "gitsubmiteditor.h" #include "gitversioncontrol.h" +#include "branchdialog.h" #include #include @@ -401,7 +402,7 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *error_message) gitContainer->addAction(createSeparator(actionManager, globalcontext, QLatin1String("Git.Sep.Branch"), this)); - m_branchListAction = new QAction(tr("List branches"), this); + m_branchListAction = new QAction(tr("Branches..."), this); command = actionManager->registerAction(m_branchListAction, "Git.BranchList", globalcontext); command->setAttribute(Core::ICommand::CA_UpdateText); connect(m_branchListAction, SIGNAL(triggered()), this, SLOT(branchList())); @@ -494,7 +495,6 @@ QString GitPlugin::getWorkingDirectory() qDebug() << Q_FUNC_INFO << "file" << workingDirectory; if (workingDirectory.isEmpty()) { - m_outputWindow->clearContents(); m_outputWindow->append(tr("Could not find working directory")); m_outputWindow->popup(false); return QString(); @@ -740,8 +740,21 @@ void GitPlugin::stashPop() void GitPlugin::branchList() { const QString workingDirectory = getWorkingDirectory(); - if (!workingDirectory.isEmpty()) - m_gitClient->branchList(workingDirectory); + if (workingDirectory.isEmpty()) + return; +#ifndef USE_BRANCHDIALOG + QString errorMessage; + BranchDialog dialog(m_core->mainWindow()); + + if (!dialog.init(m_gitClient, workingDirectory, &errorMessage)) { + m_outputWindow->append(errorMessage); + m_outputWindow->popup(false); + return; + } + dialog.exec(); +#else + m_gitClient->branchList(workingDirectory); +#endif } void GitPlugin::stashList() From 5b8008609cba3fb22d18c198eca74f21e7688578 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 19 Dec 2008 17:44:11 +0100 Subject: [PATCH 030/230] Compile Windows --- src/plugins/git/branchmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp index 0881aea654b..b02d58dbd04 100644 --- a/src/plugins/git/branchmodel.cpp +++ b/src/plugins/git/branchmodel.cpp @@ -31,7 +31,7 @@ bool BranchModel::Branch::parse(const QString &lineIn, bool *isCurrent) static inline Qt::ItemFlags typeToModelFlags(BranchModel::Type t) { Qt::ItemFlags rc = Qt::ItemIsSelectable|Qt::ItemIsEnabled; - if (t == BranchModel::BranchModel::LocalBranches) + if (t == BranchModel::LocalBranches) rc |= Qt::ItemIsUserCheckable; return rc; } From b8f013ce4a74d3347bf6688edce318b5e240b62b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 19 Dec 2008 17:49:14 +0100 Subject: [PATCH 031/230] Fixes: Remove whatsthis --- src/plugins/git/branchdialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/git/branchdialog.cpp b/src/plugins/git/branchdialog.cpp index 0918f2d6c07..8d06c871f96 100644 --- a/src/plugins/git/branchdialog.cpp +++ b/src/plugins/git/branchdialog.cpp @@ -28,6 +28,9 @@ BranchDialog::BranchDialog(QWidget *parent) : m_localModel(0), m_remoteModel(0) { + setModal(true); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + m_ui->setupUi(this); m_checkoutButton = m_ui->buttonBox->addButton(tr("Checkout"), QDialogButtonBox::AcceptRole); connect(m_checkoutButton, SIGNAL(clicked()), this, SLOT(slotCheckoutSelectedBranch())); From 89985c3d1c1e9a107585b450e63e399fa552b3a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 19 Dec 2008 17:49:44 +0100 Subject: [PATCH 032/230] Fixed header of "locals and watchers" view You couldn't disable the 'always adjust column widths to contents' logic cause of an uninitialized boolean that refused to toggle to false. --- src/plugins/debugger/watchwindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp index dfcc98250de..97d27d5f016 100644 --- a/src/plugins/debugger/watchwindow.cpp +++ b/src/plugins/debugger/watchwindow.cpp @@ -55,7 +55,8 @@ enum { INameRole = Qt::UserRole, VisualRole, ExpandedRole }; ///////////////////////////////////////////////////////////////////// WatchWindow::WatchWindow(Type type, QWidget *parent) - : QTreeView(parent), m_type(type) + : QTreeView(parent), m_type(type) + , m_alwaysResizeColumnsToContents(true) { setWindowTitle(tr("Locals and Watchers")); setAlternatingRowColors(true); From d02211674a3e71f594d08f7c66715add31a94bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Fri, 19 Dec 2008 17:53:21 +0100 Subject: [PATCH 033/230] Allow some more space for popup on most desktops Most desktops allow popups to overlap the taskbar. We should allow this additional space to be used by the completion popup. --- src/plugins/texteditor/completionwidget.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/texteditor/completionwidget.cpp b/src/plugins/texteditor/completionwidget.cpp index f9057d39078..2b2f8520e73 100644 --- a/src/plugins/texteditor/completionwidget.cpp +++ b/src/plugins/texteditor/completionwidget.cpp @@ -259,7 +259,11 @@ void CompletionWidget::updatePositionAndSize(int startPos) // Determine the position, keeping the popup on the screen const QRect cursorRect = m_editor->cursorRect(startPos); const QDesktopWidget *desktop = QApplication::desktop(); +#ifdef Q_OS_MAC const QRect screen = desktop->availableGeometry(desktop->screenNumber(this)); +#else + const QRect screen = desktop->screenGeometry(desktop->screenNumber(this)); +#endif QPoint pos = cursorRect.bottomLeft(); pos.rx() -= 16 + frameWidth; // Space for the icons From b462482cc28756982fc30a85f647eb1bfaff3150 Mon Sep 17 00:00:00 2001 From: goro Date: Fri, 19 Dec 2008 16:52:31 +0100 Subject: [PATCH 034/230] Change hidden label text from "..." to "R" --- src/plugins/coreplugin/generalsettings.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreplugin/generalsettings.ui b/src/plugins/coreplugin/generalsettings.ui index 316637e6a06..f3b50c5e4b3 100644 --- a/src/plugins/coreplugin/generalsettings.ui +++ b/src/plugins/coreplugin/generalsettings.ui @@ -73,7 +73,7 @@ Reset to default - ... + R @@ -114,7 +114,7 @@ Reset to default - ... + R From 6ef67df88b379332430deadbac91d391f203681e Mon Sep 17 00:00:00 2001 From: goro Date: Fri, 19 Dec 2008 18:25:20 +0100 Subject: [PATCH 035/230] PathChooser migration for Qt4 build config page --- src/libs/utils/pathchooser.cpp | 16 +++++- src/libs/utils/pathchooser.h | 3 ++ .../qt4buildconfigwidget.cpp | 41 +++++++-------- .../qt4projectmanager/qt4buildconfigwidget.h | 1 + .../qt4projectmanager/qt4buildconfigwidget.ui | 51 +++++++------------ 5 files changed, 53 insertions(+), 59 deletions(-) diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp index b769ea75589..91504b496c9 100644 --- a/src/libs/utils/pathchooser.cpp +++ b/src/libs/utils/pathchooser.cpp @@ -90,6 +90,7 @@ struct PathChooserPrivate PathValidatingLineEdit *m_lineEdit; PathChooser::Kind m_acceptingKind; QString m_dialogTitleOverride; + QString m_initialBrowsePathOverride; }; PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) : @@ -143,9 +144,15 @@ void PathChooser::setPath(const QString &path) void PathChooser::slotBrowse() { + emit beforeBrowsing(); + QString predefined = path(); - if (!predefined.isEmpty() && !QFileInfo(predefined).isDir()) - predefined.clear(); + if ((predefined.isEmpty() || !QFileInfo(predefined).isDir()) + && !m_d->m_initialBrowsePathOverride.isNull()) { + predefined = m_d->m_initialBrowsePathOverride; + if (!QFileInfo(predefined).isDir()) + predefined.clear(); + } // Prompt for a file/dir QString dialogTitle; @@ -271,6 +278,11 @@ void PathChooser::setPromptDialogTitle(const QString &title) m_d->m_dialogTitleOverride = title; } +void PathChooser::setInitialBrowsePathBackup(const QString &path) +{ + m_d->m_initialBrowsePathOverride = path; +} + QString PathChooser::makeDialogTitle(const QString &title) { if (m_d->m_dialogTitleOverride.isNull()) diff --git a/src/libs/utils/pathchooser.h b/src/libs/utils/pathchooser.h index f22c20120b7..5fcc8ee228c 100644 --- a/src/libs/utils/pathchooser.h +++ b/src/libs/utils/pathchooser.h @@ -71,6 +71,8 @@ public: void setPromptDialogTitle(const QString &title); + void setInitialBrowsePathBackup(const QString &path); + bool isValid() const; QString errorMessage() const; @@ -91,6 +93,7 @@ private: signals: void validChanged(); void changed(); + void beforeBrowsing(); void browsingFinished(); void returnPressed(); diff --git a/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp b/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp index 2ee2d0f8bc0..13fb5980a90 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp +++ b/src/plugins/qt4projectmanager/qt4buildconfigwidget.cpp @@ -54,6 +54,8 @@ Qt4BuildConfigWidget::Qt4BuildConfigWidget(Qt4Project *project) { m_ui = new Ui::Qt4BuildConfigWidget(); m_ui->setupUi(this); + m_ui->shadowBuildDirEdit->setPromptDialogTitle(tr("Shadow Build Directory")); + m_ui->shadowBuildDirEdit->setExpectedKind(Core::Utils::PathChooser::Directory); m_ui->invalidQtWarningLabel->setVisible(false); connect(m_ui->nameLineEdit, SIGNAL(textEdited(QString)), @@ -62,10 +64,10 @@ Qt4BuildConfigWidget::Qt4BuildConfigWidget(Qt4Project *project) connect(m_ui->shadowBuildCheckBox, SIGNAL(clicked(bool)), this, SLOT(shadowBuildCheckBoxClicked(bool))); - connect(m_ui->shadowBuildButton, SIGNAL(clicked(bool)), - this, SLOT(shadowBuildButtonClicked())); + connect(m_ui->shadowBuildDirEdit, SIGNAL(beforeBrowsing()), + this, SLOT(onBeforeBeforeShadowBuildDirBrowsed())); - connect(m_ui->shadowBuildLineEdit, SIGNAL(textEdited(QString)), + connect(m_ui->shadowBuildDirEdit, SIGNAL(changed()), this, SLOT(shadowBuildLineEditTextChanged())); connect(m_ui->qtVersionComboBox, SIGNAL(currentIndexChanged(QString)), @@ -102,10 +104,9 @@ void Qt4BuildConfigWidget::init(const QString &buildConfiguration) bool shadowBuild = m_pro->value(buildConfiguration, "useShadowBuild").toBool(); m_ui->shadowBuildCheckBox->setChecked(shadowBuild); - m_ui->shadowBuildLineEdit->setEnabled(shadowBuild); - m_ui->shadowBuildLineEdit->setText(m_pro->buildDirectory(buildConfiguration)); + m_ui->shadowBuildDirEdit->setEnabled(shadowBuild); + m_ui->shadowBuildDirEdit->setPath(m_pro->buildDirectory(buildConfiguration)); shadowBuildLineEditTextChanged(); // Update the import label - m_ui->shadowBuildButton->setEnabled(shadowBuild); } void Qt4BuildConfigWidget::changeConfigName(const QString &newName) @@ -145,47 +146,39 @@ void Qt4BuildConfigWidget::setupQtVersionsComboBox() this, SLOT(qtVersionComboBoxCurrentIndexChanged(QString))); } -void Qt4BuildConfigWidget::shadowBuildButtonClicked() +void Qt4BuildConfigWidget::onBeforeBeforeShadowBuildDirBrowsed() { - QString initialDirectory = m_ui->shadowBuildLineEdit->text(); - if (initialDirectory.isEmpty()) - initialDirectory = QFileInfo(m_pro->file()->fileName()).absolutePath(); - - QString shadowBuildDirectory = - QFileDialog::getExistingDirectory(this, tr("Shadow Build Directory"), initialDirectory ); - - if (shadowBuildDirectory != QString::null) - m_ui->shadowBuildLineEdit->setText(shadowBuildDirectory); - shadowBuildLineEditTextChanged(); + QString initialDirectory = QFileInfo(m_pro->file()->fileName()).absolutePath(); + if (!initialDirectory.isEmpty()) + m_ui->shadowBuildDirEdit->setInitialBrowsePathBackup(initialDirectory); } void Qt4BuildConfigWidget::shadowBuildCheckBoxClicked(bool checked) { - m_ui->shadowBuildLineEdit->setEnabled(checked); - m_ui->shadowBuildButton->setEnabled(checked); + m_ui->shadowBuildDirEdit->setEnabled(checked); bool b = m_ui->shadowBuildCheckBox->isChecked(); m_pro->setValue(m_buildConfiguration, "useShadowBuild", b); if (b) - m_pro->setValue(m_buildConfiguration, "buildDirectory", m_ui->shadowBuildLineEdit->text()); + m_pro->setValue(m_buildConfiguration, "buildDirectory", m_ui->shadowBuildDirEdit->path()); else m_pro->setValue(m_buildConfiguration, "buildDirectory", QVariant(QString::null)); } void Qt4BuildConfigWidget::shadowBuildLineEditTextChanged() { - m_pro->setValue(m_buildConfiguration, "buildDirectory", m_ui->shadowBuildLineEdit->text()); + m_pro->setValue(m_buildConfiguration, "buildDirectory", m_ui->shadowBuildDirEdit->path()); // if the directory already exists // check if we have a build in there and // offer to import it m_ui->importLabel->setVisible(false); if (m_ui->shadowBuildCheckBox->isChecked()) { - QString qtPath = m_pro->qt4ProjectManager()->versionManager()->findQtVersionFromMakefile(m_ui->shadowBuildLineEdit->text()); + QString qtPath = m_pro->qt4ProjectManager()->versionManager()->findQtVersionFromMakefile(m_ui->shadowBuildDirEdit->path()); if (!qtPath.isEmpty()) { m_ui->importLabel->setVisible(true); } } -// QFileInfo fi(m_ui->shadowBuildLineEdit->text()); +// QFileInfo fi(m_ui->shadowBuildDirEdit->path()); // if (fi.exists()) { // m_ui->shadowBuildLineEdit->setStyleSheet(""); // m_ui->shadowBuildLineEdit->setToolTip(""); @@ -198,7 +191,7 @@ void Qt4BuildConfigWidget::shadowBuildLineEditTextChanged() void Qt4BuildConfigWidget::importLabelClicked() { if (m_ui->shadowBuildCheckBox->isChecked()) { - QString directory = m_ui->shadowBuildLineEdit->text(); + QString directory = m_ui->shadowBuildDirEdit->path(); if (!directory.isEmpty()) { QtVersionManager *vm = m_pro->qt4ProjectManager()->versionManager(); QString qtPath = vm->findQtVersionFromMakefile(directory); diff --git a/src/plugins/qt4projectmanager/qt4buildconfigwidget.h b/src/plugins/qt4projectmanager/qt4buildconfigwidget.h index 622ce98be2e..da126023a09 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfigwidget.h +++ b/src/plugins/qt4projectmanager/qt4buildconfigwidget.h @@ -61,6 +61,7 @@ private slots: void setupQtVersionsComboBox(); void shadowBuildCheckBoxClicked(bool checked); void shadowBuildButtonClicked(); + void onBeforeBeforeShadowBuildDirBrowsed(); void shadowBuildLineEditTextChanged(); void importLabelClicked(); void qtVersionComboBoxCurrentIndexChanged(const QString &); diff --git a/src/plugins/qt4projectmanager/qt4buildconfigwidget.ui b/src/plugins/qt4projectmanager/qt4buildconfigwidget.ui index f62d4a69b53..ab5e8858611 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfigwidget.ui +++ b/src/plugins/qt4projectmanager/qt4buildconfigwidget.ui @@ -110,39 +110,6 @@ - - - - - - - 100 - 0 - - - - - 16777215 - 16777215 - - - - - - - - - 0 - 0 - - - - ... - - - - - @@ -153,6 +120,16 @@ + + + + + 0 + 0 + + + + @@ -186,6 +163,14 @@ + + + Core::Utils::PathChooser + QWidget +
utils/pathchooser.h
+ 1 +
+
From 163083c42cc37e5c2947b59974bfbac3a1075c4d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 19 Dec 2008 21:16:34 +0100 Subject: [PATCH 036/230] remove cruft --- shared/proparser/profileevaluator.cpp | 14 -------------- shared/proparser/profileevaluator.h | 2 -- 2 files changed, 16 deletions(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index ea280b45b4d..0d80706701a 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -2254,20 +2254,6 @@ void ProFileEvaluator::errorMessage(const QString &message) qWarning("%s", qPrintable(message)); } -// This function is unneeded and still retained. See log message for reason. -QStringList ProFileEvaluator::absFileNames(const QString &variableName) -{ - QStringList sources_out; - QFileInfo fi(d->m_origfile); - QDir dir(fi.absoluteDir()); - foreach (const QString &fn, values(variableName)) { - const QString absName = QDir::cleanPath(dir.absoluteFilePath(fn)); - d->expandPatternHelper(fn, absName, sources_out); - } - - return sources_out; -} - void ProFileEvaluator::setVerbose(bool on) { d->m_verbose = on; diff --git a/shared/proparser/profileevaluator.h b/shared/proparser/profileevaluator.h index 14805421603..9b7b77fb0c7 100644 --- a/shared/proparser/profileevaluator.h +++ b/shared/proparser/profileevaluator.h @@ -66,8 +66,6 @@ public: ProFileEvaluator::TemplateType templateType(); virtual bool contains(const QString &variableName) const; - QStringList absFileNames(const QString &variableName); - QStringList absFileName(const QString &name); void setVerbose(bool on); // Default is false void setCumulative(bool on); // Default is true! void setOutputDir(const QString &dir); // Default is empty From 18f8097adbb65b9ab1f2c3b3781672031895f211 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 19 Dec 2008 21:19:38 +0100 Subject: [PATCH 037/230] unobfuscate in multiple ways: getcwd() => currentDirectory() --- shared/proparser/profileevaluator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index 0d80706701a..6226a5b3f4d 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -188,7 +188,7 @@ public: QString format(const char *format) const; QString currentFileName() const; - QString getcwd() const; + QString currentDirectory() const; ProFile *currentProFile() const; bool evaluateConditionalFunction(const QString &function, const QString &arguments, bool *result); @@ -958,7 +958,7 @@ QString ProFileEvaluator::Private::currentFileName() const return QString(); } -QString ProFileEvaluator::Private::getcwd() const +QString ProFileEvaluator::Private::currentDirectory() const { ProFile *cur = m_profileStack.top(); QFileInfo fi(cur->fileName()); @@ -1747,7 +1747,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct } QString fileName = args.first(); // ### this breaks if we have include(c:/reallystupid.pri) but IMHO that's really bad style. - QDir currentProPath(getcwd()); + QDir currentProPath(currentDirectory()); fileName = QDir::cleanPath(currentProPath.absoluteFilePath(fileName)); ok = evaluateFile(fileName, &ok); break; @@ -1834,7 +1834,7 @@ bool ProFileEvaluator::Private::evaluateConditionalFunction(const QString &funct break; } //regular expression I guess - QString dirstr = getcwd(); + QString dirstr = currentDirectory(); int slsh = file.lastIndexOf(Option::dir_sep); if (slsh != -1) { dirstr = file.left(slsh+1); @@ -1873,7 +1873,7 @@ QStringList ProFileEvaluator::Private::values(const QString &variableName, return QStringList(m_outputDir); if (variableName == QLatin1String("PWD") || //current working dir (of _FILE_) variableName == QLatin1String("IN_PWD")) - return QStringList(getcwd()); + return QStringList(currentDirectory()); if (variableName == QLatin1String("DIR_SEPARATOR")) return QStringList(Option::dir_sep); if (variableName == QLatin1String("DIRLIST_SEPARATOR")) From 922909b05aef4a39b604c2a3c4e188d405b1545a Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 19 Dec 2008 21:35:10 +0100 Subject: [PATCH 038/230] cache profile's parent directory --- shared/proparser/profileevaluator.cpp | 6 ++---- shared/proparser/proitems.cpp | 6 ++++++ shared/proparser/proitems.h | 2 ++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/shared/proparser/profileevaluator.cpp b/shared/proparser/profileevaluator.cpp index 6226a5b3f4d..cdfcb05fae3 100644 --- a/shared/proparser/profileevaluator.cpp +++ b/shared/proparser/profileevaluator.cpp @@ -625,8 +625,7 @@ bool ProFileEvaluator::Private::visitBeginProFile(ProFile * pro) m_cumulative = cumulative; } - QString fn = pro->fileName(); - ok = QDir::setCurrent(QFileInfo(fn).absolutePath()); + ok = QDir::setCurrent(pro->directoryName()); } return ok; @@ -961,8 +960,7 @@ QString ProFileEvaluator::Private::currentFileName() const QString ProFileEvaluator::Private::currentDirectory() const { ProFile *cur = m_profileStack.top(); - QFileInfo fi(cur->fileName()); - return fi.absolutePath(); + return cur->directoryName(); } QStringList ProFileEvaluator::Private::expandVariableReferences(const QString &str) diff --git a/shared/proparser/proitems.cpp b/shared/proparser/proitems.cpp index 346517c0f0f..1e686c5578b 100644 --- a/shared/proparser/proitems.cpp +++ b/shared/proparser/proitems.cpp @@ -275,6 +275,7 @@ ProFile::ProFile(const QString &fileName) QFileInfo fi(fileName); m_displayFileName = fi.fileName(); + m_directoryName = fi.absolutePath(); } ProFile::~ProFile() @@ -291,6 +292,11 @@ QString ProFile::fileName() const return m_fileName; } +QString ProFile::directoryName() const +{ + return m_directoryName; +} + void ProFile::setModified(bool modified) { m_modified = modified; diff --git a/shared/proparser/proitems.h b/shared/proparser/proitems.h index a3736086e70..01ecf0f0f2d 100644 --- a/shared/proparser/proitems.h +++ b/shared/proparser/proitems.h @@ -209,6 +209,7 @@ public: QString displayFileName() const; QString fileName() const; + QString directoryName() const; void setModified(bool modified); bool isModified() const; @@ -218,6 +219,7 @@ public: private: QString m_fileName; QString m_displayFileName; + QString m_directoryName; bool m_modified; }; From 286e45b473e79a8dd361aea385902e7a3aa4dbb6 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 22 Dec 2008 10:24:52 +0100 Subject: [PATCH 039/230] Compile. Removed declaration of slot shadowBuildButtonClicked(). --- src/plugins/qt4projectmanager/qt4buildconfigwidget.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/qt4projectmanager/qt4buildconfigwidget.h b/src/plugins/qt4projectmanager/qt4buildconfigwidget.h index da126023a09..c7910b44b04 100644 --- a/src/plugins/qt4projectmanager/qt4buildconfigwidget.h +++ b/src/plugins/qt4projectmanager/qt4buildconfigwidget.h @@ -60,7 +60,6 @@ private slots: void changeConfigName(const QString &newName); void setupQtVersionsComboBox(); void shadowBuildCheckBoxClicked(bool checked); - void shadowBuildButtonClicked(); void onBeforeBeforeShadowBuildDirBrowsed(); void shadowBuildLineEditTextChanged(); void importLabelClicked(); From 864f07d438308dfec322bf83ad29e2d6154083c2 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 22 Dec 2008 10:46:15 +0100 Subject: [PATCH 040/230] Initial work on the test suite for the C++ front-end semantic pass. --- tests/auto/cplusplus/semantic/semantic.pro | 5 + .../auto/cplusplus/semantic/tst_semantic.cpp | 96 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 tests/auto/cplusplus/semantic/semantic.pro create mode 100644 tests/auto/cplusplus/semantic/tst_semantic.cpp diff --git a/tests/auto/cplusplus/semantic/semantic.pro b/tests/auto/cplusplus/semantic/semantic.pro new file mode 100644 index 00000000000..71a8b5fab5f --- /dev/null +++ b/tests/auto/cplusplus/semantic/semantic.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +include(../shared/shared.pri) +QT = core + +SOURCES += tst_semantic.cpp diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp new file mode 100644 index 00000000000..d9200bee4b5 --- /dev/null +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -0,0 +1,96 @@ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +CPLUSPLUS_USE_NAMESPACE + +class tst_Semantic: public QObject +{ + Q_OBJECT + + Control control; + +public: + TranslationUnit *parse(const QByteArray &source, + TranslationUnit::ParseMode mode) + { + StringLiteral *fileId = control.findOrInsertFileName(""); + TranslationUnit *unit = new TranslationUnit(&control, fileId); + unit->setSource(source.constData(), source.length()); + unit->parse(mode); + return unit; + } + + class Document { + Q_DISABLE_COPY(Document) + + public: + Document(TranslationUnit *unit) + : unit(unit), globals(new Scope()) + { } + + ~Document() + { delete globals; } + + void check() + { + QVERIFY(unit); + QVERIFY(unit->ast()); + Semantic sem(unit->control()); + TranslationUnitAST *ast = unit->ast()->asTranslationUnit(); + QVERIFY(ast); + for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) { + sem.check(decl, globals); + } + } + + TranslationUnit *unit; + Scope *globals; + }; + + QSharedPointer document(const QByteArray &source) + { + TranslationUnit *unit = parse(source, TranslationUnit::ParseTranlationUnit); + QSharedPointer doc(new Document(unit)); + doc->check(); + return doc; + } + +private slots: + void function_declarations(); +}; + +void tst_Semantic::function_declarations() +{ + QSharedPointer doc = document("void foo();"); + QCOMPARE(doc->globals->symbolCount(), 1U); + + Declaration *decl = doc->globals->symbolAt(0)->asDeclaration(); + QVERIFY(decl); + + FullySpecifiedType declTy = decl->type(); + Function *funTy = declTy->asFunction(); + QVERIFY(funTy); + QVERIFY(funTy->returnType()->isVoidType()); + QCOMPARE(funTy->argumentCount(), 0U); + + QVERIFY(decl->name()->isNameId()); + Identifier *funId = decl->name()->asNameId()->identifier(); + QVERIFY(funId); + + const QByteArray foo(funId->chars(), funId->size()); + QCOMPARE(foo, QByteArray("foo")); +} + + +QTEST_APPLESS_MAIN(tst_Semantic) +#include "tst_semantic.moc" From 50e4203b52e4dc5a2453aa58f8b54e6bfcd0c918 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 22 Dec 2008 10:56:29 +0100 Subject: [PATCH 041/230] More testing --- .../auto/cplusplus/semantic/tst_semantic.cpp | 66 ++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index d9200bee4b5..239fcd33556 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -66,10 +67,12 @@ public: } private slots: - void function_declarations(); + void function_declaration_1(); + void function_declaration_2(); + void function_definition_1(); }; -void tst_Semantic::function_declarations() +void tst_Semantic::function_declaration_1() { QSharedPointer doc = document("void foo();"); QCOMPARE(doc->globals->symbolCount(), 1U); @@ -91,6 +94,65 @@ void tst_Semantic::function_declarations() QCOMPARE(foo, QByteArray("foo")); } +void tst_Semantic::function_declaration_2() +{ + QSharedPointer doc = document("void foo(const QString &s);"); + QCOMPARE(doc->globals->symbolCount(), 1U); + + Declaration *decl = doc->globals->symbolAt(0)->asDeclaration(); + QVERIFY(decl); + + FullySpecifiedType declTy = decl->type(); + Function *funTy = declTy->asFunction(); + QVERIFY(funTy); + QVERIFY(funTy->returnType()->isVoidType()); + QCOMPARE(funTy->argumentCount(), 1U); + + // check the formal argument. + Argument *arg = funTy->argumentAt(0)->asArgument(); + QVERIFY(arg); + QVERIFY(arg->name()); + QVERIFY(! arg->hasInitializer()); + + // check the argument's name. + NameId *argNameId = arg->name()->asNameId(); + QVERIFY(argNameId); + + Identifier *argId = argNameId->identifier(); + QVERIFY(argId); + + QCOMPARE(QByteArray(argId->chars(), argId->size()), QByteArray("s")); + + // check the type of the formal argument + FullySpecifiedType argTy = arg->type(); + QVERIFY(argTy->isReferenceType()); + QVERIFY(argTy->asReferenceType()->elementType().isConst()); + + QVERIFY(decl->name()->isNameId()); + Identifier *funId = decl->name()->asNameId()->identifier(); + QVERIFY(funId); + + const QByteArray foo(funId->chars(), funId->size()); + QCOMPARE(foo, QByteArray("foo")); +} + +void tst_Semantic::function_definition_1() +{ + QSharedPointer doc = document("void foo() {}"); + QCOMPARE(doc->globals->symbolCount(), 1U); + + Function *funTy = doc->globals->symbolAt(0)->asFunction(); + QVERIFY(funTy); + QVERIFY(funTy->returnType()->isVoidType()); + QCOMPARE(funTy->argumentCount(), 0U); + + QVERIFY(funTy->name()->isNameId()); + Identifier *funId = funTy->name()->asNameId()->identifier(); + QVERIFY(funId); + + const QByteArray foo(funId->chars(), funId->size()); + QCOMPARE(foo, QByteArray("foo")); +} QTEST_APPLESS_MAIN(tst_Semantic) #include "tst_semantic.moc" From 3050034c2b88c4a57a0e8d024bf23c467e54e004 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 22 Dec 2008 10:56:47 +0100 Subject: [PATCH 042/230] Compile the semantic test suite. --- tests/auto/cplusplus/cplusplus.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/cplusplus/cplusplus.pro b/tests/auto/cplusplus/cplusplus.pro index 97256476470..55e6cd83f0e 100644 --- a/tests/auto/cplusplus/cplusplus.pro +++ b/tests/auto/cplusplus/cplusplus.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs -SUBDIRS = shared ast +SUBDIRS = shared ast semantic CONFIG += ordered From d8336257cb1da778ab74f1edce68f855dd862242 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 22 Dec 2008 10:59:22 +0100 Subject: [PATCH 043/230] Check the argument's type in tst_Semantic::function_declaration_2. --- tests/auto/cplusplus/semantic/tst_semantic.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 239fcd33556..30cbc73fc01 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -127,6 +127,13 @@ void tst_Semantic::function_declaration_2() FullySpecifiedType argTy = arg->type(); QVERIFY(argTy->isReferenceType()); QVERIFY(argTy->asReferenceType()->elementType().isConst()); + NamedType *namedTy = argTy->asReferenceType()->elementType()->asNamedType(); + QVERIFY(namedTy); + QVERIFY(namedTy->name()); + Identifier *namedTypeId = namedTy->name()->asNameId()->identifier(); + QVERIFY(namedTypeId); + QCOMPARE(QByteArray(namedTypeId->chars(), namedTypeId->size()), + QByteArray("QString")); QVERIFY(decl->name()->isNameId()); Identifier *funId = decl->name()->asNameId()->identifier(); From 753ddb7ce076a12df07b2f800fe785cf659277df Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 22 Dec 2008 11:40:53 +0100 Subject: [PATCH 044/230] Some cleanup in the C++ preprocessor. Introduced pp-scanner.cpp, renamed `pp' to `Preprocessor' and removed useless #includes. --- src/libs/cplusplus/TypeOfExpression.cpp | 2 +- src/libs/cplusplus/cplusplus.pro | 5 +- src/libs/cplusplus/pp-cctype.h | 6 +- src/libs/cplusplus/pp-client.h | 6 +- src/libs/cplusplus/pp-engine.cpp | 54 ++--- src/libs/cplusplus/pp-engine.h | 10 +- src/libs/cplusplus/pp-environment.h | 6 +- src/libs/cplusplus/pp-internal.h | 78 ------ src/libs/cplusplus/pp-macro-expander.cpp | 17 +- src/libs/cplusplus/pp-scanner.cpp | 296 +++++++++++++++++++++++ src/libs/cplusplus/pp-scanner.h | 282 +-------------------- src/libs/cplusplus/pp.h | 12 +- src/plugins/cpptools/cppmodelmanager.cpp | 2 +- 13 files changed, 372 insertions(+), 404 deletions(-) delete mode 100644 src/libs/cplusplus/pp-internal.h create mode 100644 src/libs/cplusplus/pp-scanner.cpp diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index 46c2042d0f3..8c4ccb05e2f 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -136,7 +136,7 @@ QString TypeOfExpression::preprocessedExpression(const QString &expression, processEnvironment(documents, thisDocument, &env, &processed); const QByteArray code = expression.toUtf8(); - pp preproc(0, env); + Preprocessor preproc(0, env); QByteArray preprocessedCode; preproc("", code, &preprocessedCode); return QString::fromUtf8(preprocessedCode); diff --git a/src/libs/cplusplus/cplusplus.pro b/src/libs/cplusplus/cplusplus.pro index 35ec8a070b3..b8bde402825 100644 --- a/src/libs/cplusplus/cplusplus.pro +++ b/src/libs/cplusplus/cplusplus.pro @@ -22,13 +22,13 @@ HEADERS += \ TypePrettyPrinter.h \ ResolveExpression.h \ LookupContext.h \ + pp.h \ pp-cctype.h \ pp-engine.h \ pp-macro-expander.h \ pp-scanner.h \ pp-client.h \ pp-environment.h \ - pp-internal.h \ pp-macro.h SOURCES += \ @@ -46,6 +46,7 @@ SOURCES += \ LookupContext.cpp \ pp-engine.cpp \ pp-environment.cpp \ - pp-macro-expander.cpp + pp-macro-expander.cpp \ + pp-scanner.cpp RESOURCES += cplusplus.qrc diff --git a/src/libs/cplusplus/pp-cctype.h b/src/libs/cplusplus/pp-cctype.h index 532f56a7e1d..d55d6c2e4e9 100644 --- a/src/libs/cplusplus/pp-cctype.h +++ b/src/libs/cplusplus/pp-cctype.h @@ -50,8 +50,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_CCTYPE_H -#define PP_CCTYPE_H +#ifndef CPLUSPLUS_PP_CCTYPE_H +#define CPLUSPLUS_PP_CCTYPE_H #include @@ -73,4 +73,4 @@ inline bool CPLUSPLUS_EXPORT pp_isspace (int __ch) } // namespace CPlusPlus -#endif // PP_CCTYPE_H +#endif // CPLUSPLUS_PP_CCTYPE_H diff --git a/src/libs/cplusplus/pp-client.h b/src/libs/cplusplus/pp-client.h index e866be4aa89..d7dd49b18b7 100644 --- a/src/libs/cplusplus/pp-client.h +++ b/src/libs/cplusplus/pp-client.h @@ -31,8 +31,8 @@ ** ***************************************************************************/ -#ifndef PP_CLIENT_H -#define PP_CLIENT_H +#ifndef CPLUSPLUS_PP_CLIENT_H +#define CPLUSPLUS_PP_CLIENT_H #include @@ -79,4 +79,4 @@ public: } // namespace CPlusPlus -#endif // PP_CLIENT_H +#endif // CPLUSPLUS_PP_CLIENT_H diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 0ed09f224de..a6186c6b7c6 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -451,7 +451,7 @@ private: } // end of anonymous namespace -pp::pp (Client *client, Environment &env) +Preprocessor::Preprocessor(Client *client, Environment &env) : client(client), env(env), expand(env) @@ -459,7 +459,7 @@ pp::pp (Client *client, Environment &env) resetIfLevel (); } -void pp::pushState(const State &s) +void Preprocessor::pushState(const State &s) { _savedStates.append(state()); _source = s.source; @@ -467,7 +467,7 @@ void pp::pushState(const State &s) _dot = s.dot; } -pp::State pp::state() const +Preprocessor::State Preprocessor::state() const { State state; state.source = _source; @@ -476,7 +476,7 @@ pp::State pp::state() const return state; } -void pp::popState() +void Preprocessor::popState() { const State &state = _savedStates.last(); _source = state.source; @@ -485,7 +485,7 @@ void pp::popState() _savedStates.removeLast(); } -void pp::operator () (const QByteArray &filename, +void Preprocessor::operator () (const QByteArray &filename, const QByteArray &source, QByteArray *result) { @@ -497,7 +497,7 @@ void pp::operator () (const QByteArray &filename, env.currentFile = previousFile; } -pp::State pp::createStateFromSource(const QByteArray &source) const +Preprocessor::State Preprocessor::createStateFromSource(const QByteArray &source) const { State state; state.source = source; @@ -512,7 +512,7 @@ pp::State pp::createStateFromSource(const QByteArray &source) const return state; } -void pp::operator()(const QByteArray &source, QByteArray *result) +void Preprocessor::operator()(const QByteArray &source, QByteArray *result) { pushState(createStateFromSource(source)); @@ -700,27 +700,27 @@ void pp::operator()(const QByteArray &source, QByteArray *result) env.currentLine = previousCurrentLine; } -const char *pp::startOfToken(const Token &token) const +const char *Preprocessor::startOfToken(const Token &token) const { return _source.constBegin() + token.begin(); } -const char *pp::endOfToken(const Token &token) const +const char *Preprocessor::endOfToken(const Token &token) const { return _source.constBegin() + token.end(); } -QByteArray pp::tokenSpell(const Token &token) const +QByteArray Preprocessor::tokenSpell(const Token &token) const { const QByteArray text = QByteArray::fromRawData(_source.constBegin() + token.offset, token.length); return text; } -QByteArray pp::tokenText(const Token &token) const +QByteArray Preprocessor::tokenText(const Token &token) const { const QByteArray text(_source.constBegin() + token.offset, token.length); return text; } -void pp::processDirective(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processDirective(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); ++tk; // skip T_POUND @@ -771,7 +771,7 @@ void pp::processDirective(TokenIterator firstToken, TokenIterator lastToken) } } -QVector pp::tokenize(const QByteArray &text) const +QVector Preprocessor::tokenize(const QByteArray &text) const { QVector tokens; Lexer lex(text.constBegin(), text.constEnd()); @@ -784,7 +784,7 @@ QVector pp::tokenize(const QByteArray &text) const return tokens; } -void pp::processInclude(bool skipCurentPath, +void Preprocessor::processInclude(bool skipCurentPath, TokenIterator firstToken, TokenIterator lastToken, bool acceptMacros) { @@ -836,7 +836,7 @@ void pp::processInclude(bool skipCurentPath, } } -void pp::processDefine(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -921,7 +921,7 @@ void pp::processDefine(TokenIterator firstToken, TokenIterator lastToken) client->macroAdded(macro); } -void pp::processIf(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processIf(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -948,7 +948,7 @@ void pp::processIf(TokenIterator firstToken, TokenIterator lastToken) } } -void pp::processElse(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processElse(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -961,7 +961,7 @@ void pp::processElse(TokenIterator firstToken, TokenIterator lastToken) } } -void pp::processElif(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processElif(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); ++tk; // skip T_POUND @@ -980,7 +980,7 @@ void pp::processElif(TokenIterator firstToken, TokenIterator lastToken) } } -void pp::processEndif(TokenIterator, TokenIterator) +void Preprocessor::processEndif(TokenIterator, TokenIterator) { if (iflevel == 0 && !skipping()) { // std::cerr << "*** WARNING #endif without #if" << std::endl; @@ -992,7 +992,7 @@ void pp::processEndif(TokenIterator, TokenIterator) } } -void pp::processIfdef(bool checkUndefined, +void Preprocessor::processIfdef(bool checkUndefined, TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -1013,7 +1013,7 @@ void pp::processIfdef(bool checkUndefined, } } -void pp::processUndef(TokenIterator firstToken, TokenIterator lastToken) +void Preprocessor::processUndef(TokenIterator firstToken, TokenIterator lastToken) { RangeLexer tk(firstToken, lastToken); @@ -1029,14 +1029,14 @@ void pp::processUndef(TokenIterator firstToken, TokenIterator lastToken) } } -void pp::resetIfLevel () +void Preprocessor::resetIfLevel () { iflevel = 0; _skipping[iflevel] = false; _true_test[iflevel] = false; } -pp::PP_DIRECTIVE_TYPE pp::classifyDirective (const QByteArray &__directive) const +Preprocessor::PP_DIRECTIVE_TYPE Preprocessor::classifyDirective (const QByteArray &__directive) const { switch (__directive.size()) { @@ -1085,7 +1085,7 @@ pp::PP_DIRECTIVE_TYPE pp::classifyDirective (const QByteArray &__directive) cons return PP_UNKNOWN_DIRECTIVE; } -bool pp::testIfLevel() +bool Preprocessor::testIfLevel() { const bool result = !_skipping[iflevel++]; _skipping[iflevel] = _skipping[iflevel - 1]; @@ -1093,10 +1093,10 @@ bool pp::testIfLevel() return result; } -int pp::skipping() const +int Preprocessor::skipping() const { return _skipping[iflevel]; } -Value pp::evalExpression(TokenIterator firstToken, TokenIterator lastToken, +Value Preprocessor::evalExpression(TokenIterator firstToken, TokenIterator lastToken, const QByteArray &source) const { ExpressionEvaluator eval(&env); @@ -1104,7 +1104,7 @@ Value pp::evalExpression(TokenIterator firstToken, TokenIterator lastToken, return result; } -bool pp::isQtReservedWord (const QByteArray ¯oId) const +bool Preprocessor::isQtReservedWord (const QByteArray ¯oId) const { const int size = macroId.size(); if (size == 9 && macroId.at(0) == 'Q' && macroId == "Q_SIGNALS") diff --git a/src/libs/cplusplus/pp-engine.h b/src/libs/cplusplus/pp-engine.h index e7c0af68fb1..7ff0005c393 100644 --- a/src/libs/cplusplus/pp-engine.h +++ b/src/libs/cplusplus/pp-engine.h @@ -50,8 +50,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_ENGINE_H -#define PP_ENGINE_H +#ifndef CPLUSPLUS_PP_ENGINE_H +#define CPLUSPLUS_PP_ENGINE_H #include "pp-client.h" @@ -134,7 +134,7 @@ namespace CPlusPlus { #undef PP_DEFINE_BIN_OP }; - class CPLUSPLUS_EXPORT pp + class CPLUSPLUS_EXPORT Preprocessor { Client *client; Environment &env; @@ -182,7 +182,7 @@ namespace CPlusPlus { State createStateFromSource(const QByteArray &source) const; public: - pp(Client *client, Environment &env); + Preprocessor(Client *client, Environment &env); void operator()(const QByteArray &filename, const QByteArray &source, @@ -228,4 +228,4 @@ namespace CPlusPlus { } // namespace CPlusPlus -#endif // PP_ENGINE_H +#endif // CPLUSPLUS_PP_ENGINE_H diff --git a/src/libs/cplusplus/pp-environment.h b/src/libs/cplusplus/pp-environment.h index 4ba6b9353c4..97d0fe02d3c 100644 --- a/src/libs/cplusplus/pp-environment.h +++ b/src/libs/cplusplus/pp-environment.h @@ -50,8 +50,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_ENVIRONMENT_H -#define PP_ENVIRONMENT_H +#ifndef CPLUSPLUS_PP_ENVIRONMENT_H +#define CPLUSPLUS_PP_ENVIRONMENT_H #include "CPlusPlusForwardDeclarations.h" @@ -108,4 +108,4 @@ private: } // namespace CPlusPlus -#endif // PP_ENVIRONMENT_H +#endif // CPLUSPLUS_PP_ENVIRONMENT_H diff --git a/src/libs/cplusplus/pp-internal.h b/src/libs/cplusplus/pp-internal.h deleted file mode 100644 index f3b8aef835e..00000000000 --- a/src/libs/cplusplus/pp-internal.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** -** Non-Open Source Usage -** -** Licensees may use this file in accordance with the Qt Beta Version -** License Agreement, Agreement version 2.2 provided with the Software or, -** alternatively, in accordance with the terms contained in a written -** agreement between you and Nokia. -** -** GNU General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the packaging -** of this file. Please review the following information to ensure GNU -** General Public Licensing requirements will be met: -** -** http://www.fsf.org/licensing/licenses/info/GPLv2.html and -** http://www.gnu.org/copyleft/gpl.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt GPL Exception -** version 1.3, included in the file GPL_EXCEPTION.txt in this package. -** -***************************************************************************/ -/* - Copyright 2005 Roberto Raggi - - Permission to use, copy, modify, distribute, and sell this software and its - documentation for any purpose is hereby granted without fee, provided that - the above copyright notice appear in all copies and that both that - copyright notice and this permission notice appear in supporting - documentation. - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ - -#ifndef PP_INTERNAL_H -#define PP_INTERNAL_H - -#include - -namespace CPlusPlus { -namespace _PP_internal { - -inline bool comment_p (const char *__first, const char *__last) -{ - if (__first == __last) - return false; - - if (*__first != '/') - return false; - - if (++__first == __last) - return false; - - return (*__first == '/' || *__first == '*'); -} - -} // _PP_internal -} // namespace CPlusPlus - -#endif // PP_INTERNAL_H diff --git a/src/libs/cplusplus/pp-macro-expander.cpp b/src/libs/cplusplus/pp-macro-expander.cpp index 21148d24461..6a7d7e75df8 100644 --- a/src/libs/cplusplus/pp-macro-expander.cpp +++ b/src/libs/cplusplus/pp-macro-expander.cpp @@ -32,11 +32,26 @@ ***************************************************************************/ #include "pp.h" +#include "pp-cctype.h" #include "pp-macro-expander.h" #include using namespace CPlusPlus; +inline static bool comment_p (const char *__first, const char *__last) +{ + if (__first == __last) + return false; + + if (*__first != '/') + return false; + + if (++__first == __last) + return false; + + return (*__first == '/' || *__first == '*'); +} + MacroExpander::MacroExpander (Environment &env, pp_frame *frame) : env(env), frame(frame), lines(0), generated_lines(0) @@ -137,7 +152,7 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, __result->append(__first, next_pos - __first); __first = next_pos; } - else if (_PP_internal::comment_p (__first, __last)) + else if (comment_p (__first, __last)) { __first = skip_comment_or_divop (__first, __last); int n = skip_comment_or_divop.lines; diff --git a/src/libs/cplusplus/pp-scanner.cpp b/src/libs/cplusplus/pp-scanner.cpp new file mode 100644 index 00000000000..8f0f9bf9ae8 --- /dev/null +++ b/src/libs/cplusplus/pp-scanner.cpp @@ -0,0 +1,296 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ +/* + Copyright 2005 Roberto Raggi + + Permission to use, copy, modify, distribute, and sell this software and its + documentation for any purpose is hereby granted without fee, provided that + the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation. + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "pp-scanner.h" +#include "pp-cctype.h" + +using namespace CPlusPlus; + +const char *pp_skip_blanks::operator () (const char *__first, const char *__last) +{ + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + if (*__first == '\\') { + const char *__begin = __first; + ++__begin; + + if (__begin != __last && *__begin == '\n') + ++__first; + else + break; + } else if (*__first == '\n' || !pp_isspace (*__first)) + break; + } + + return __first; +} + +const char *pp_skip_whitespaces::operator () (const char *__first, const char *__last) +{ + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + if (! pp_isspace (*__first)) + break; + } + + return __first; +} + +const char *pp_skip_comment_or_divop::operator () (const char *__first, const char *__last) +{ + enum { + MAYBE_BEGIN, + BEGIN, + MAYBE_END, + END, + IN_COMMENT, + IN_CXX_COMMENT + } state (MAYBE_BEGIN); + + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + switch (state) { + default: + break; + + case MAYBE_BEGIN: + if (*__first != '/') + return __first; + + state = BEGIN; + break; + + case BEGIN: + if (*__first == '*') + state = IN_COMMENT; + else if (*__first == '/') + state = IN_CXX_COMMENT; + else + return __first; + break; + + case IN_COMMENT: + if (*__first == '*') + state = MAYBE_END; + break; + + case IN_CXX_COMMENT: + if (*__first == '\n') + return __first; + break; + + case MAYBE_END: + if (*__first == '/') + state = END; + else if (*__first != '*') + state = IN_COMMENT; + break; + + case END: + return __first; + } + } + + return __first; +} + +const char *pp_skip_identifier::operator () (const char *__first, const char *__last) +{ + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + if (! pp_isalnum (*__first) && *__first != '_') + break; + } + + return __first; +} + +const char *pp_skip_number::operator () (const char *__first, const char *__last) +{ + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + if (! pp_isalnum (*__first) && *__first != '.') + break; + } + + return __first; +} + +const char *pp_skip_string_literal::operator () (const char *__first, const char *__last) +{ + enum { + BEGIN, + IN_STRING, + QUOTE, + END + } state (BEGIN); + + lines = 0; + + for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + switch (state) + { + default: + break; + + case BEGIN: + if (*__first != '\"') + return __first; + state = IN_STRING; + break; + + case IN_STRING: + if (! (*__first != '\n')) + return __last; + + if (*__first == '\"') + state = END; + else if (*__first == '\\') + state = QUOTE; + break; + + case QUOTE: + state = IN_STRING; + break; + + case END: + return __first; + } + } + + return __first; +} + +const char *pp_skip_char_literal::operator () (const char *__first, const char *__last) +{ + enum { + BEGIN, + IN_STRING, + QUOTE, + END + } state (BEGIN); + + lines = 0; + + for (; state != END && __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { + switch (state) + { + default: + break; + + case BEGIN: + if (*__first != '\'') + return __first; + state = IN_STRING; + break; + + case IN_STRING: + if (! (*__first != '\n')) + return __last; + + if (*__first == '\'') + state = END; + else if (*__first == '\\') + state = QUOTE; + break; + + case QUOTE: + state = IN_STRING; + break; + } + } + + return __first; +} + +const char *pp_skip_argument::operator () (const char *__first, const char *__last) +{ + int depth = 0; + lines = 0; + + while (__first != __last) { + if (!depth && (*__first == ')' || *__first == ',')) + break; + else if (*__first == '(') + ++depth, ++__first; + else if (*__first == ')') + --depth, ++__first; + else if (*__first == '\"') { + __first = skip_string_literal (__first, __last); + lines += skip_string_literal.lines; + } else if (*__first == '\'') { + __first = skip_char_literal (__first, __last); + lines += skip_char_literal.lines; + } else if (*__first == '/') { + __first = skip_comment_or_divop (__first, __last); + lines += skip_comment_or_divop.lines; + } else if (pp_isalpha (*__first) || *__first == '_') { + __first = skip_identifier (__first, __last); + lines += skip_identifier.lines; + } else if (pp_isdigit (*__first)) { + __first = skip_number (__first, __last); + lines += skip_number.lines; + } else if (*__first == '\n') { + ++__first; + ++lines; + } else + ++__first; + } + + return __first; +} + diff --git a/src/libs/cplusplus/pp-scanner.h b/src/libs/cplusplus/pp-scanner.h index c2e768912fa..71bd04476ba 100644 --- a/src/libs/cplusplus/pp-scanner.h +++ b/src/libs/cplusplus/pp-scanner.h @@ -50,266 +50,57 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_SCANNER_H -#define PP_SCANNER_H +#ifndef CPLUSPLUS_PP_SCANNER_H +#define CPLUSPLUS_PP_SCANNER_H namespace CPlusPlus { struct pp_skip_blanks { int lines; - - - const char *operator () (const char *__first, const char *__last) - { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - if (*__first == '\\') - { - const char *__begin = __first; - ++__begin; - - if (__begin != __last && *__begin == '\n') - ++__first; - else - break; - } - else if (*__first == '\n' || !pp_isspace (*__first)) - break; - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_whitespaces { int lines; - - const char *operator () (const char *__first, const char *__last) - { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - if (! pp_isspace (*__first)) - break; - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_comment_or_divop { int lines; - - const char *operator () (const char *__first, const char *__last) - { - enum { - MAYBE_BEGIN, - BEGIN, - MAYBE_END, - END, - IN_COMMENT, - IN_CXX_COMMENT - } state (MAYBE_BEGIN); - - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - switch (state) - { - default: - assert (0); - break; - - case MAYBE_BEGIN: - if (*__first != '/') - return __first; - - state = BEGIN; - break; - - case BEGIN: - if (*__first == '*') - state = IN_COMMENT; - else if (*__first == '/') - state = IN_CXX_COMMENT; - else - return __first; - break; - - case IN_COMMENT: - if (*__first == '*') - state = MAYBE_END; - break; - - case IN_CXX_COMMENT: - if (*__first == '\n') - return __first; - break; - - case MAYBE_END: - if (*__first == '/') - state = END; - else if (*__first != '*') - state = IN_COMMENT; - break; - - case END: - return __first; - } - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_identifier { int lines; - - const char *operator () (const char *__first, const char *__last) - { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - if (! pp_isalnum (*__first) && *__first != '_') - break; - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_number { int lines; - - const char *operator () (const char *__first, const char *__last) - { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - if (! pp_isalnum (*__first) && *__first != '.') - break; - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_string_literal { int lines; - - const char *operator () (const char *__first, const char *__last) - { - enum { - BEGIN, - IN_STRING, - QUOTE, - END - } state (BEGIN); - - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - switch (state) - { - default: - assert (0); - break; - - case BEGIN: - if (*__first != '\"') - return __first; - state = IN_STRING; - break; - - case IN_STRING: - if (! (*__first != '\n')) - return __last; - - if (*__first == '\"') - state = END; - else if (*__first == '\\') - state = QUOTE; - break; - - case QUOTE: - state = IN_STRING; - break; - - case END: - return __first; - } - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_char_literal { int lines; - - const char *operator () (const char *__first, const char *__last) - { - enum { - BEGIN, - IN_STRING, - QUOTE, - END - } state (BEGIN); - - lines = 0; - - for (; state != END && __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) - { - switch (state) - { - default: - assert (0); - break; - - case BEGIN: - if (*__first != '\'') - return __first; - state = IN_STRING; - break; - - case IN_STRING: - if (! (*__first != '\n')) - return __last; - - if (*__first == '\'') - state = END; - else if (*__first == '\\') - state = QUOTE; - break; - - case QUOTE: - state = IN_STRING; - break; - } - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; struct pp_skip_argument @@ -321,60 +112,9 @@ struct pp_skip_argument pp_skip_comment_or_divop skip_comment_or_divop; int lines; - - const char *operator () (const char *__first, const char *__last) - { - int depth = 0; - lines = 0; - - while (__first != __last) - { - if (!depth && (*__first == ')' || *__first == ',')) - break; - else if (*__first == '(') - ++depth, ++__first; - else if (*__first == ')') - --depth, ++__first; - else if (*__first == '\"') - { - __first = skip_string_literal (__first, __last); - lines += skip_string_literal.lines; - } - else if (*__first == '\'') - { - __first = skip_char_literal (__first, __last); - lines += skip_char_literal.lines; - } - else if (*__first == '/') - { - __first = skip_comment_or_divop (__first, __last); - lines += skip_comment_or_divop.lines; - } - else if (pp_isalpha (*__first) || *__first == '_') - { - __first = skip_identifier (__first, __last); - lines += skip_identifier.lines; - } - else if (pp_isdigit (*__first)) - { - __first = skip_number (__first, __last); - lines += skip_number.lines; - } - else if (*__first == '\n') - { - ++__first; - ++lines; - } - else - ++__first; - } - - return __first; - } + const char *operator () (const char *first, const char *last); }; } // namespace CPlusPlus -#endif // PP_SCANNER_H - -// kate: space-indent on; indent-width 2; replace-tabs on; +#endif // CPLUSPLUS_PP_SCANNER_H diff --git a/src/libs/cplusplus/pp.h b/src/libs/cplusplus/pp.h index 2dee3e87f1d..2cf40eed096 100644 --- a/src/libs/cplusplus/pp.h +++ b/src/libs/cplusplus/pp.h @@ -50,15 +50,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef PP_H -#define PP_H +#ifndef CPLUSPLUS_PREPROCESSOR_H +#define CPLUSPLUS_PREPROCESSOR_H -#include -#include -#include - -#include "pp-cctype.h" -#include "pp-internal.h" #include "pp-macro.h" #include "pp-environment.h" #include "pp-scanner.h" @@ -66,4 +60,4 @@ #include "pp-engine.h" #include "pp-client.h" -#endif // PP_H +#endif // CPLUSPLUS_PREPROCESSOR_H diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 6dad51a6434..df611294751 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -144,7 +144,7 @@ private: QPointer m_modelManager; Snapshot m_snapshot; Environment env; - pp m_proc; + Preprocessor m_proc; QStringList m_includePaths; QStringList m_systemIncludePaths; QMap m_workingCopy; From ae4725e954487052c84cb5e2b94dec0b08edd120 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 22 Dec 2008 13:09:26 +0100 Subject: [PATCH 045/230] Introduced CPlusPlus::Managed. Managed is an helper base class that simplify the usage of memory pools. --- shared/cplusplus/AST.cpp | 9 --------- shared/cplusplus/AST.h | 8 ++------ shared/cplusplus/MemoryPool.cpp | 15 +++++++++++++++ shared/cplusplus/MemoryPool.h | 15 +++++++++++++++ 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 248ed13a027..7774d4d71fa 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -381,15 +381,6 @@ UsingDirectiveAST *AST::asUsingDirective() WhileStatementAST *AST::asWhileStatement() { return dynamic_cast(this); } -void *AST::operator new(size_t size, MemoryPool *pool) -{ return pool->allocate(size); } - -void AST::operator delete(void *) -{ } - -void AST::operator delete(void *, MemoryPool *) -{ } - void AST::accept(ASTVisitor *visitor) { if (visitor->preVisit(this)) diff --git a/shared/cplusplus/AST.h b/shared/cplusplus/AST.h index fd7cec40deb..c4b0f7fe76f 100644 --- a/shared/cplusplus/AST.h +++ b/shared/cplusplus/AST.h @@ -55,12 +55,12 @@ #include "CPlusPlusForwardDeclarations.h" #include "ASTfwd.h" -#include +#include "MemoryPool.h" CPLUSPLUS_BEGIN_HEADER CPLUSPLUS_BEGIN_NAMESPACE -class CPLUSPLUS_EXPORT AST +class CPLUSPLUS_EXPORT AST: public Managed { AST(const AST &other); void operator =(const AST &other); @@ -74,10 +74,6 @@ public: static void accept(AST *ast, ASTVisitor *visitor) { if (ast) ast->accept(visitor); } - void *operator new(size_t size, MemoryPool *pool); - void operator delete(void *); - void operator delete(void *, MemoryPool *); - virtual unsigned firstToken() const = 0; virtual unsigned lastToken() const = 0; diff --git a/shared/cplusplus/MemoryPool.cpp b/shared/cplusplus/MemoryPool.cpp index 639bb2c6164..a7c04691449 100644 --- a/shared/cplusplus/MemoryPool.cpp +++ b/shared/cplusplus/MemoryPool.cpp @@ -112,4 +112,19 @@ void *MemoryPool::allocate_helper(size_t size) return addr; } +Managed::Managed() +{ } + +Managed::~Managed() +{ } + +void *Managed::operator new(size_t size, MemoryPool *pool) +{ return pool->allocate(size); } + +void Managed::operator delete(void *) +{ } + +void Managed::operator delete(void *, MemoryPool *) +{ } + CPLUSPLUS_END_NAMESPACE diff --git a/shared/cplusplus/MemoryPool.h b/shared/cplusplus/MemoryPool.h index 8d1f09b54e8..9647b673a6e 100644 --- a/shared/cplusplus/MemoryPool.h +++ b/shared/cplusplus/MemoryPool.h @@ -55,6 +55,7 @@ #include "CPlusPlusForwardDeclarations.h" #include +#include CPLUSPLUS_BEGIN_HEADER CPLUSPLUS_BEGIN_NAMESPACE @@ -99,6 +100,20 @@ private: }; }; +class CPLUSPLUS_EXPORT Managed +{ + Managed(const Managed &other); + void operator = (const Managed &other); + +public: + Managed(); + virtual ~Managed(); + + void *operator new(size_t size, MemoryPool *pool); + void operator delete(void *); + void operator delete(void *, MemoryPool *); +}; + CPLUSPLUS_END_NAMESPACE CPLUSPLUS_END_HEADER From 1e0f06e4e821fa7eb6964d08b53b75494c54766b Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 22 Dec 2008 13:27:01 +0100 Subject: [PATCH 046/230] Introduced expandNamespace(), expandClass(), expandBlock(), and expandFunction(). This should simplify the merging of the improved lookup context. --- src/libs/cplusplus/LookupContext.cpp | 244 +++++++++++++++------------ src/libs/cplusplus/LookupContext.h | 17 ++ 2 files changed, 150 insertions(+), 111 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index cbf6b1ef660..28f8b0dd58f 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -274,129 +274,151 @@ void LookupContext::expand(const QList &scopes, QList *expande } } +void LookupContext::expandNamespace(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const +{ + Namespace *ns = scope->owner()->asNamespace(); + if (! ns) + return; + + if (Name *nsName = ns->name()) { + const QList namespaceList = resolveNamespace(nsName, visibleScopes); + foreach (Symbol *otherNs, namespaceList) { + if (otherNs == ns) + continue; + expand(otherNs->asNamespace()->members(), visibleScopes, expandedScopes); + } + } + + for (unsigned i = 0; i < scope->symbolCount(); ++i) { // ### make me fast + Symbol *symbol = scope->symbolAt(i); + if (Namespace *ns = symbol->asNamespace()) { + if (! ns->name()) { + expand(ns->members(), visibleScopes, expandedScopes); + } + } else if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) { + const QList candidates = resolveNamespace(u->name(), visibleScopes); + for (int j = 0; j < candidates.size(); ++j) { + expand(candidates.at(j)->asNamespace()->members(), + visibleScopes, expandedScopes); + } + } else if (Enum *e = symbol->asEnum()) { + expand(e->members(), visibleScopes, expandedScopes); + } + } +} + +void LookupContext::expandClass(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const +{ + Class *klass = scope->owner()->asClass(); + if (! klass) + return; + + for (unsigned i = 0; i < scope->symbolCount(); ++i) { + Symbol *symbol = scope->symbolAt(i); + if (Class *nestedClass = symbol->asClass()) { + if (! nestedClass->name()) { + expand(nestedClass->members(), visibleScopes, expandedScopes); + } + } else if (Enum *e = symbol->asEnum()) { + expand(e->members(), visibleScopes, expandedScopes); + } + } + + if (klass->baseClassCount()) { + QList classVisibleScopes = visibleScopes; + for (Scope *scope = klass->scope(); scope; scope = scope->enclosingScope()) { + if (scope->isNamespaceScope()) { + Namespace *enclosingNamespace = scope->owner()->asNamespace(); + if (enclosingNamespace->name()) { + const QList nsList = resolveNamespace(enclosingNamespace->name(), + visibleScopes); + foreach (Symbol *ns, nsList) { + expand(ns->asNamespace()->members(), classVisibleScopes, + &classVisibleScopes); + } + } + } + } + + for (unsigned i = 0; i < klass->baseClassCount(); ++i) { + BaseClass *baseClass = klass->baseClassAt(i); + Name *baseClassName = baseClass->name(); + const QList baseClassCandidates = resolveClass(baseClassName, + classVisibleScopes); + if (baseClassCandidates.isEmpty()) { + Overview overview; + qDebug() << "unresolved base class:" << overview.prettyName(baseClassName); + } + + for (int j = 0; j < baseClassCandidates.size(); ++j) { + Class *baseClassSymbol = baseClassCandidates.at(j)->asClass(); + expand(baseClassSymbol->members(), visibleScopes, expandedScopes); + } + } + } +} + +void LookupContext::expandBlock(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const +{ + for (unsigned i = 0; i < scope->symbolCount(); ++i) { + Symbol *symbol = scope->symbolAt(i); + if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) { + const QList candidates = resolveNamespace(u->name(), + visibleScopes); + for (int j = 0; j < candidates.size(); ++j) { + expand(candidates.at(j)->asNamespace()->members(), + visibleScopes, expandedScopes); + } + } + + } +} + +void LookupContext::expandFunction(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const +{ + Function *function = scope->owner()->asFunction(); + if (! expandedScopes->contains(function->arguments())) + expandedScopes->append(function->arguments()); + if (QualifiedNameId *q = function->name()->asQualifiedNameId()) { + Name *nestedNameSpec = 0; + if (q->nameCount() == 1 && q->isGlobal()) + nestedNameSpec = q->nameAt(0); + else + nestedNameSpec = control()->qualifiedNameId(q->names(), q->nameCount() - 1, + q->isGlobal()); + const QList candidates = resolveClassOrNamespace(nestedNameSpec, visibleScopes); + for (int j = 0; j < candidates.size(); ++j) { + expand(candidates.at(j)->asScopedSymbol()->members(), + visibleScopes, expandedScopes); + } + } +} + void LookupContext::expand(Scope *scope, const QList &visibleScopes, QList *expandedScopes) const { - Overview overview; - - if (expandedScopes->contains(scope)) { - //qDebug() << "skipped:" << overview.prettyName(scope->owner()->name()); + if (expandedScopes->contains(scope)) return; - } expandedScopes->append(scope); if (scope->isNamespaceScope()) { - Namespace *ns = scope->owner()->asNamespace(); - Name *nsName = ns->name(); - if (nsName) { - QList namespaceList = resolveNamespace(nsName, visibleScopes); - foreach (Symbol *otherNs, namespaceList) { - if (otherNs == ns) - continue; - expand(otherNs->asNamespace()->members(), visibleScopes, expandedScopes); - } - //qDebug() << "*** found:" << namespaceList.count() << "namespace aliases"; - } - //qDebug() << "namespace scope" << overview.prettyName(ns->name()) - //<< ns->fileName() << ns->line(); - for (unsigned i = 0; i < scope->symbolCount(); ++i) { // ### make me fast - Symbol *symbol = scope->symbolAt(i); - if (Namespace *ns = symbol->asNamespace()) { - if (! ns->name()) { - expand(ns->members(), visibleScopes, expandedScopes); - } - } else if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) { - QList candidates = resolveNamespace(u->name(), visibleScopes); - //qDebug() << "found:" << candidates.count() << "namespaces to import for:" - //<< overview.prettyName(u->name()); - for (int j = 0; j < candidates.size(); ++j) { - expand(candidates.at(j)->asNamespace()->members(), - visibleScopes, expandedScopes); - } - } else if (Enum *e = symbol->asEnum()) { - expand(e->members(), visibleScopes, expandedScopes); - } - } + expandNamespace(scope, visibleScopes, expandedScopes); } else if (scope->isClassScope()) { - Class *klass = scope->owner()->asClass(); - for (unsigned i = 0; i < scope->symbolCount(); ++i) { - Symbol *symbol = scope->symbolAt(i); - if (Class *nestedClass = symbol->asClass()) { - if (! nestedClass->name()) { - expand(nestedClass->members(), visibleScopes, expandedScopes); - } - } else if (Enum *e = symbol->asEnum()) { - expand(e->members(), visibleScopes, expandedScopes); - } - } - - if (klass->baseClassCount()) { - QList classVisibleScopes = visibleScopes; - for (Scope *scope = klass->scope(); scope; scope = scope->enclosingScope()) { - if (scope->isNamespaceScope()) { - Namespace *enclosingNamespace = scope->owner()->asNamespace(); - if (enclosingNamespace->name()) { - QList nsList = resolveNamespace(enclosingNamespace->name(), - visibleScopes); - foreach (Symbol *ns, nsList) { - expand(ns->asNamespace()->members(), classVisibleScopes, &classVisibleScopes); - } - } - } - } - - for (unsigned i = 0; i < klass->baseClassCount(); ++i) { - BaseClass *baseClass = klass->baseClassAt(i); - Name *baseClassName = baseClass->name(); - QList baseClassCandidates = resolveClass(baseClassName, classVisibleScopes); - if (baseClassCandidates.isEmpty()) { - Overview overview; - qDebug() << "unresolved base class:" << overview.prettyName(baseClassName); - } - for (int j = 0; j < baseClassCandidates.size(); ++j) { - Class *baseClassSymbol = baseClassCandidates.at(j)->asClass(); - expand(baseClassSymbol->members(), visibleScopes, expandedScopes); - } - } - } + expandClass(scope, visibleScopes, expandedScopes); } else if (scope->isBlockScope()) { - //qDebug() << "block scope" << overview.prettyName(scope->owner()->name()); - for (unsigned i = 0; i < scope->symbolCount(); ++i) { - Symbol *symbol = scope->symbolAt(i); - if (UsingNamespaceDirective *u = symbol->asUsingNamespaceDirective()) { - QList candidates = resolveNamespace(u->name(), visibleScopes); - //qDebug() << "found:" << candidates.count() << "namespaces to import for:" - //<< overview.prettyName(u->name()); - for (int j = 0; j < candidates.size(); ++j) { - expand(candidates.at(j)->asNamespace()->members(), - visibleScopes, expandedScopes); - } - } - - } + expandBlock(scope, visibleScopes, expandedScopes); } else if (scope->isFunctionScope()) { - Function *function = scope->owner()->asFunction(); - //qDebug() << "function scope" << overview.prettyName(function->name()); - if (! expandedScopes->contains(function->arguments())) - expandedScopes->append(function->arguments()); - if (QualifiedNameId *q = function->name()->asQualifiedNameId()) { - //qDebug() << "**** here:" << overview.prettyName(function->name()); - Name *nestedNameSpec = 0; - if (q->nameCount() == 1 && q->isGlobal()) - nestedNameSpec = q->nameAt(0); - else - nestedNameSpec = control()->qualifiedNameId(q->names(), q->nameCount() - 1, - q->isGlobal()); - QList candidates = resolveClassOrNamespace(nestedNameSpec, visibleScopes); - //qDebug() << "**** found:" << candidates.count() << "class or namespace for:" - //<< overview.prettyName(nestedNameSpec); - for (int j = 0; j < candidates.size(); ++j) { - expand(candidates.at(j)->asScopedSymbol()->members(), - visibleScopes, expandedScopes); - } - } + expandFunction(scope, visibleScopes, expandedScopes); } else if (scope->isPrototypeScope()) { //qDebug() << "prototype scope" << overview.prettyName(scope->owner()->name()); } diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index e1aec69d122..58d5baf439d 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -124,9 +124,26 @@ public: void expand(Scope *scope, const QList &visibleScopes, QList *expandedScopes) const; + void expandNamespace(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const; + + void expandClass(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const; + + void expandBlock(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const; + + void expandFunction(Scope *scope, + const QList &visibleScopes, + QList *expandedScopes) const; + private: QList buildVisibleScopes(); + private: Control *_control; From e325aa38d91c9d11b9645004e786924c49e2b325 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 22 Dec 2008 13:55:42 +0100 Subject: [PATCH 047/230] Nicer implementation of CPlusPlus::Macro. --- src/libs/cplusplus/LookupContext.cpp | 1 - src/libs/cplusplus/pp-engine.cpp | 79 +++++++------- src/libs/cplusplus/pp-environment.cpp | 26 ++--- src/libs/cplusplus/pp-macro-expander.cpp | 24 ++--- src/libs/cplusplus/pp-macro-expander.h | 4 + src/libs/cplusplus/pp-macro.h | 113 +++++++++++++++------ src/plugins/cppeditor/cppeditor.cpp | 4 +- src/plugins/cppeditor/cpphoverhandler.cpp | 5 +- src/plugins/cpptools/cppcodecompletion.cpp | 4 +- 9 files changed, 153 insertions(+), 107 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 28f8b0dd58f..ed70e5b2168 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -40,7 +40,6 @@ #include #include -#include #include using namespace CPlusPlus; diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index a6186c6b7c6..6c5930de182 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -600,19 +600,15 @@ void Preprocessor::operator()(const QByteArray &source, QByteArray *result) if (! m) { result->append(spell); } else { - if (! m->function_like) { + if (! m->isFunctionLike()) { if (_dot->isNot(T_LPAREN)) { if (client) client->startExpandingMacro(identifierToken->offset, *m, spell); - m->hidden = true; - - expand(m->definition.constBegin(), - m->definition.constEnd(), - result); - - m->hidden = false; + m->setHidden(true); + expand(m->definition(), result); + m->setHidden(false); if (client) client->stopExpandingMacro(_dot->offset, *m); @@ -624,13 +620,9 @@ void Preprocessor::operator()(const QByteArray &source, QByteArray *result) if (client) client->startExpandingMacro(identifierToken->offset, *m, spell); - m->hidden = true; - - expand(m->definition.constBegin(), - m->definition.constEnd(), - &tmp); - - m->hidden = false; + m->setHidden(true); + expand(m->definition(), &tmp); + m->setHidden(false); if (client) client->stopExpandingMacro(_dot->offset, *m); @@ -641,7 +633,7 @@ void Preprocessor::operator()(const QByteArray &source, QByteArray *result) if (_dot->is(T_IDENTIFIER)) { const QByteArray id = tokenSpell(*_dot); Macro *macro = env.resolve(id); - if (macro && macro->function_like) + if (macro && macro->isFunctionLike()) m = macro; } popState(); @@ -656,7 +648,7 @@ void Preprocessor::operator()(const QByteArray &source, QByteArray *result) // collect the actual arguments if (_dot->isNot(T_LPAREN)) { // ### warnng expected T_LPAREN - result->append(m->name); + result->append(m->name()); continue; } @@ -852,30 +844,30 @@ void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastTok } Macro macro; - macro.fileName = env.currentFile; - macro.line = env.currentLine; - macro.name = tokenText(*tk); + macro.setFileName(env.currentFile); + macro.setLine(env.currentLine); + macro.setName(tokenText(*tk)); ++tk; // skip T_IDENTIFIER if (tk->is(T_LPAREN) && ! tk->whitespace) { // a function-like macro definition - macro.function_like = true; + macro.setFunctionLike(true); ++tk; // skip T_LPAREN if (tk->is(T_IDENTIFIER)) { - macro.formals.append(tokenText(*tk)); + macro.addFormal(tokenText(*tk)); ++tk; // skip T_IDENTIFIER while (tk->is(T_COMMA)) { ++tk;// skip T_COMMA if (tk->isNot(T_IDENTIFIER)) break; - macro.formals.append(tokenText(*tk)); + macro.addFormal(tokenText(*tk)); ++tk; // skip T_IDENTIFIER } } if (tk->is(T_DOT_DOT_DOT)) { - macro.variadics = true; + macro.setVariadic(true); ++tk; // skip T_DOT_DOT_DOT } @@ -887,32 +879,31 @@ void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastTok ++tk; // skip T_RPAREN } - QByteArray macroId = macro.name; - const bool isQtWord = isQtReservedWord(macroId); + if (isQtReservedWord(macro.name())) { + QByteArray macroId = macro.name(); - if (macro.function_like) { - macroId += '('; - for (int i = 0; i < macro.formals.size(); ++i) { - if (i != 0) - macroId += ", "; - - const QByteArray formal = macro.formals.at(i); - macroId += formal; + if (macro.isFunctionLike()) { + macroId += '('; + bool fst = true; + foreach (const QByteArray formal, macro.formals()) { + if (! fst) + macroId += ", "; + fst = false; + macroId += formal; + } + macroId += ')'; } - macroId += ')'; - } - if (isQtWord) - macro.definition = macroId; - else { + macro.setDefinition(macroId); + } else { // ### make me fast! const char *startOfDefinition = startOfToken(*tk); const char *endOfDefinition = startOfToken(*lastToken); - macro.definition.append(startOfDefinition, - endOfDefinition - startOfDefinition); - macro.definition.replace("\\\n", " "); - macro.definition.replace('\n', ' '); - macro.definition = macro.definition.trimmed(); + QByteArray definition(startOfDefinition, + endOfDefinition - startOfDefinition); + definition.replace("\\\n", " "); + definition.replace('\n', ' '); + macro.setDefinition(definition.trimmed()); } env.bind(macro); diff --git a/src/libs/cplusplus/pp-environment.cpp b/src/libs/cplusplus/pp-environment.cpp index 60827d4b9b2..7b93c275d3d 100644 --- a/src/libs/cplusplus/pp-environment.cpp +++ b/src/libs/cplusplus/pp-environment.cpp @@ -91,10 +91,10 @@ Macro *Environment::macroAt(unsigned index) const Macro *Environment::bind(const Macro &__macro) { - Q_ASSERT(! __macro.name.isEmpty()); + Q_ASSERT(! __macro.name().isEmpty()); Macro *m = new Macro (__macro); - m->hashcode = hash_code(m->name); + m->_hashcode = hash_code(m->name()); if (++_macro_count == _allocated_macros) { if (! _allocated_macros) @@ -110,8 +110,8 @@ Macro *Environment::bind(const Macro &__macro) if (! _hash || _macro_count > (_hash_count >> 1)) { rehash(); } else { - const unsigned h = m->hashcode % _hash_count; - m->next = _hash[h]; + const unsigned h = m->_hashcode % _hash_count; + m->_next = _hash[h]; _hash[h] = m; } @@ -121,10 +121,10 @@ Macro *Environment::bind(const Macro &__macro) Macro *Environment::remove(const QByteArray &name) { Macro macro; - macro.name = name; - macro.hidden = true; - macro.fileName = currentFile; - macro.line = currentLine; + macro.setName(name); + macro.setHidden(true); + macro.setFileName(currentFile); + macro.setLine(currentLine); return bind(macro); } @@ -198,10 +198,10 @@ Macro *Environment::resolve (const QByteArray &name) const return 0; Macro *it = _hash[hash_code (name) % _hash_count]; - for (; it; it = it->next) { - if (it->name != name) + for (; it; it = it->_next) { + if (it->name() != name) continue; - else if (it->hidden) + else if (it->isHidden()) return 0; else break; } @@ -229,8 +229,8 @@ void Environment::rehash() for (Macro **it = firstMacro(); it != lastMacro(); ++it) { Macro *m= *it; - const unsigned h = m->hashcode % _hash_count; - m->next = _hash[h]; + const unsigned h = m->_hashcode % _hash_count; + m->_next = _hash[h]; _hash[h] = m; } } diff --git a/src/libs/cplusplus/pp-macro-expander.cpp b/src/libs/cplusplus/pp-macro-expander.cpp index 6a7d7e75df8..5b0f20b66c5 100644 --- a/src/libs/cplusplus/pp-macro-expander.cpp +++ b/src/libs/cplusplus/pp-macro-expander.cpp @@ -62,7 +62,7 @@ const QByteArray *MacroExpander::resolve_formal(const QByteArray &__name) if (! (frame && frame->expanding_macro)) return 0; - const QVector &formals = frame->expanding_macro->formals; + const QVector formals = frame->expanding_macro->formals(); for (int index = 0; index < formals.size(); ++index) { const QByteArray formal = formals.at(index); @@ -213,7 +213,7 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, } Macro *macro = env.resolve (fast_name); - if (! macro || macro->hidden || env.hide_next) + if (! macro || macro->isHidden() || env.hide_next) { if (fast_name.size () == 7 && fast_name [0] == 'd' && fast_name == "defined") env.hide_next = true; @@ -260,19 +260,19 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, continue; } - if (! macro->function_like) + if (! macro->isFunctionLike()) { Macro *m = 0; - if (! macro->definition.isEmpty()) + if (! macro->definition().isEmpty()) { - macro->hidden = true; + macro->setHidden(true); QByteArray __tmp; __tmp.reserve (256); MacroExpander expand_macro (env); - expand_macro (macro->definition.constBegin (), macro->definition.constEnd (), &__tmp); + expand_macro (macro->definition(), &__tmp); generated_lines += expand_macro.lines; if (! __tmp.isEmpty ()) @@ -292,7 +292,7 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, *__result += __tmp; } - macro->hidden = false; + macro->setHidden(false); } if (! m) @@ -348,9 +348,9 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, pp_frame frame (macro, actuals); MacroExpander expand_macro (env, &frame); - macro->hidden = true; - expand_macro (macro->definition.constBegin (), macro->definition.constEnd (), __result); - macro->hidden = false; + macro->setHidden(true); + expand_macro (macro->definition(), __result); + macro->setHidden(false); generated_lines += expand_macro.lines; } else @@ -366,8 +366,8 @@ const char *MacroExpander::skip_argument_variadics (QVector const &_ { const char *arg_end = skip_argument (__first, __last); - while (__macro->variadics && __first != arg_end && arg_end != __last && *arg_end == ',' - && (__actuals.size () + 1) == __macro->formals.size ()) + while (__macro->isVariadic() && __first != arg_end && arg_end != __last && *arg_end == ',' + && (__actuals.size () + 1) == __macro->formals().size ()) { arg_end = skip_argument (++arg_end, __last); } diff --git a/src/libs/cplusplus/pp-macro-expander.h b/src/libs/cplusplus/pp-macro-expander.h index 2959977bb15..3e6217476fa 100644 --- a/src/libs/cplusplus/pp-macro-expander.h +++ b/src/libs/cplusplus/pp-macro-expander.h @@ -88,6 +88,10 @@ namespace CPlusPlus { const char *operator () (const char *first, const char *last, QByteArray *result); + const char *operator () (const QByteArray &source, + QByteArray *result) + { return operator()(source.constBegin(), source.constEnd(), result); } + const char *skip_argument_variadics (const QVector &actuals, Macro *macro, const char *first, const char *last); diff --git a/src/libs/cplusplus/pp-macro.h b/src/libs/cplusplus/pp-macro.h index 9f5e32752c5..36fe7995ad2 100644 --- a/src/libs/cplusplus/pp-macro.h +++ b/src/libs/cplusplus/pp-macro.h @@ -64,59 +64,110 @@ namespace CPlusPlus { class CPLUSPLUS_EXPORT Macro { public: - QByteArray name; - QByteArray definition; - QVector formals; - QByteArray fileName; - int line; - Macro *next; - unsigned hashcode; - - union - { - unsigned state; - - struct - { - unsigned hidden: 1; - unsigned function_like: 1; - unsigned variadics: 1; - }; - }; - - inline Macro(): - line(0), - next(0), - hashcode(0), - state(0) + Macro() + : _next(0), + _hashcode(0), + _line(0), + _state(0) { } + QByteArray name() const + { return _name; } + + void setName(const QByteArray &name) + { _name = name; } + + QByteArray definition() const + { return _definition; } + + void setDefinition(const QByteArray &definition) + { _definition = definition; } + + QVector formals() const + { return _formals; } + + void addFormal(const QByteArray &formal) + { _formals.append(formal); } + + QByteArray fileName() const + { return _fileName; } + + void setFileName(const QByteArray &fileName) + { _fileName = fileName; } + + unsigned line() const + { return _line; } + + void setLine(unsigned line) + { _line = line; } + + bool isHidden() const + { return _hidden; } + + void setHidden(bool isHidden) + { _hidden = isHidden; } + + bool isFunctionLike() const + { return _functionLike; } + + void setFunctionLike(bool isFunctionLike) + { _functionLike = isFunctionLike; } + + bool isVariadic() const + { return _variadic; } + + void setVariadic(bool isVariadic) + { _variadic = isVariadic; } + QString toString() const { QString text; - if (hidden) + if (_hidden) text += QLatin1String("#undef "); else text += QLatin1String("#define "); - text += QString::fromUtf8(name.constData(), name.size()); - if (function_like) { + text += QString::fromUtf8(_name.constData(), _name.size()); + if (_functionLike) { text += QLatin1Char('('); bool first = true; - foreach (const QByteArray formal, formals) { + foreach (const QByteArray formal, _formals) { if (! first) text += QLatin1String(", "); else first = false; text += QString::fromUtf8(formal.constData(), formal.size()); } - if (variadics) + if (_variadic) text += QLatin1String("..."); text += QLatin1Char(')'); } text += QLatin1Char(' '); - text += QString::fromUtf8(definition.constData(), definition.size()); + text += QString::fromUtf8(_definition.constData(), _definition.size()); return text; } + +// ### private + Macro *_next; + unsigned _hashcode; + +private: + QByteArray _name; + QByteArray _definition; + QVector _formals; + QByteArray _fileName; + unsigned _line; + + union + { + unsigned _state; + + struct + { + unsigned _hidden: 1; + unsigned _functionLike: 1; + unsigned _variadic: 1; + }; + }; }; } // namespace CPlusPlus diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index bfc9f3fd5c1..1eb298aa378 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -543,8 +543,8 @@ void CPPEditor::jumpToDefinition() foreach (const Document::MacroUse use, doc->macroUses()) { if (use.contains(endOfName - 1)) { const Macro ¯o = use.macro(); - const QString fileName = QString::fromUtf8(macro.fileName); - if (openCppEditorAt(fileName, macro.line, 0)) + const QString fileName = QString::fromUtf8(macro.fileName()); + if (openCppEditorAt(fileName, macro.line(), 0)) return; // done } } diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index f4060d0b60f..ba97e5a212a 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -271,8 +271,9 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in if (m_toolTip.isEmpty()) { foreach (const Document::MacroUse &use, doc->macroUses()) { if (use.contains(pos)) { - m_toolTip = use.macro().toString(); - m_helpId = use.macro().name; + const Macro m = use.macro(); + m_toolTip = m.toString(); + m_helpId = m.name(); break; } } diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 1e54a2ae092..f8c5fe9b48a 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -741,7 +741,7 @@ void CppCodeCompletion::addMacros(const LookupContext &context) processed.insert(fn); if (Document::Ptr doc = context.document(fn)) { foreach (const Macro ¯o, doc->definedMacros()) { - macroNames.insert(macro.name); + macroNames.insert(macro.name()); } todo += doc->includedFiles(); } @@ -749,7 +749,7 @@ void CppCodeCompletion::addMacros(const LookupContext &context) foreach (const QByteArray ¯oName, macroNames) { TextEditor::CompletionItem item(this); - item.m_text = QString::fromLatin1(macroName.constData(), macroName.length()); + item.m_text = QString::fromUtf8(macroName.constData(), macroName.length()); item.m_icon = m_icons.macroIcon(); m_completions.append(item); } From 0422bcbbd599cafe87735087804a434b78e353ff Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 22 Dec 2008 14:10:47 +0100 Subject: [PATCH 048/230] Some more clean up in the preprocessor. --- src/libs/cplusplus/CppDocument.h | 3 +- src/libs/cplusplus/Macro.cpp | 89 +++++++++++++++++++ src/libs/cplusplus/{pp-macro.h => Macro.h} | 34 +------ src/libs/cplusplus/PreprocessorClient.cpp | 42 +++++++++ .../{pp-client.h => PreprocessorClient.h} | 15 ++-- ...onment.cpp => PreprocessorEnvironment.cpp} | 15 ++-- ...nvironment.h => PreprocessorEnvironment.h} | 4 +- src/libs/cplusplus/cplusplus.pro | 12 +-- src/libs/cplusplus/pp-engine.h | 2 +- src/libs/cplusplus/pp-macro-expander.cpp | 6 +- src/libs/cplusplus/pp.h | 6 +- 11 files changed, 164 insertions(+), 64 deletions(-) create mode 100644 src/libs/cplusplus/Macro.cpp rename src/libs/cplusplus/{pp-macro.h => Macro.h} (79%) create mode 100644 src/libs/cplusplus/PreprocessorClient.cpp rename src/libs/cplusplus/{pp-client.h => PreprocessorClient.h} (94%) rename src/libs/cplusplus/{pp-environment.cpp => PreprocessorEnvironment.cpp} (95%) rename src/libs/cplusplus/{pp-environment.h => PreprocessorEnvironment.h} (97%) diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index 98b5ed1a2ad..d872dd3a1af 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -35,8 +35,7 @@ #define CPPDOCUMENT_H #include - -#include "pp-macro.h" +#include "Macro.h" #include #include diff --git a/src/libs/cplusplus/Macro.cpp b/src/libs/cplusplus/Macro.cpp new file mode 100644 index 00000000000..d5492b983b7 --- /dev/null +++ b/src/libs/cplusplus/Macro.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ +/* + Copyright 2005 Roberto Raggi + + Permission to use, copy, modify, distribute, and sell this software and its + documentation for any purpose is hereby granted without fee, provided that + the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation. + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "Macro.h" + +using namespace CPlusPlus; + +Macro::Macro() + : _next(0), + _hashcode(0), + _line(0), + _state(0) +{ } + +QString Macro::toString() const +{ + QString text; + if (_hidden) + text += QLatin1String("#undef "); + else + text += QLatin1String("#define "); + text += QString::fromUtf8(_name.constData(), _name.size()); + if (_functionLike) { + text += QLatin1Char('('); + bool first = true; + foreach (const QByteArray formal, _formals) { + if (! first) + text += QLatin1String(", "); + else + first = false; + text += QString::fromUtf8(formal.constData(), formal.size()); + } + if (_variadic) + text += QLatin1String("..."); + text += QLatin1Char(')'); + } + text += QLatin1Char(' '); + text += QString::fromUtf8(_definition.constData(), _definition.size()); + return text; +} diff --git a/src/libs/cplusplus/pp-macro.h b/src/libs/cplusplus/Macro.h similarity index 79% rename from src/libs/cplusplus/pp-macro.h rename to src/libs/cplusplus/Macro.h index 36fe7995ad2..3957f13fab6 100644 --- a/src/libs/cplusplus/pp-macro.h +++ b/src/libs/cplusplus/Macro.h @@ -64,12 +64,7 @@ namespace CPlusPlus { class CPLUSPLUS_EXPORT Macro { public: - Macro() - : _next(0), - _hashcode(0), - _line(0), - _state(0) - { } + Macro(); QByteArray name() const { return _name; } @@ -119,32 +114,7 @@ public: void setVariadic(bool isVariadic) { _variadic = isVariadic; } - QString toString() const - { - QString text; - if (_hidden) - text += QLatin1String("#undef "); - else - text += QLatin1String("#define "); - text += QString::fromUtf8(_name.constData(), _name.size()); - if (_functionLike) { - text += QLatin1Char('('); - bool first = true; - foreach (const QByteArray formal, _formals) { - if (! first) - text += QLatin1String(", "); - else - first = false; - text += QString::fromUtf8(formal.constData(), formal.size()); - } - if (_variadic) - text += QLatin1String("..."); - text += QLatin1Char(')'); - } - text += QLatin1Char(' '); - text += QString::fromUtf8(_definition.constData(), _definition.size()); - return text; - } + QString toString() const; // ### private Macro *_next; diff --git a/src/libs/cplusplus/PreprocessorClient.cpp b/src/libs/cplusplus/PreprocessorClient.cpp new file mode 100644 index 00000000000..2eb5656446e --- /dev/null +++ b/src/libs/cplusplus/PreprocessorClient.cpp @@ -0,0 +1,42 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ + +#include "PreprocessorClient.h" + +using namespace CPlusPlus; + +Client::Client() +{ } + +Client::~Client() +{ } diff --git a/src/libs/cplusplus/pp-client.h b/src/libs/cplusplus/PreprocessorClient.h similarity index 94% rename from src/libs/cplusplus/pp-client.h rename to src/libs/cplusplus/PreprocessorClient.h index d7dd49b18b7..2d37dac3e6d 100644 --- a/src/libs/cplusplus/pp-client.h +++ b/src/libs/cplusplus/PreprocessorClient.h @@ -35,10 +35,12 @@ #define CPLUSPLUS_PP_CLIENT_H #include +#include -#include -#include -#include +QT_BEGIN_NAMESPACE +class QByteArray; +class QString; +QT_END_NAMESPACE namespace CPlusPlus { @@ -56,11 +58,8 @@ public: }; public: - Client() - { } - - virtual ~Client() - { } + Client(); + virtual ~Client(); virtual void macroAdded(const Macro ¯o) = 0; virtual void sourceNeeded(QString &fileName, IncludeType mode, diff --git a/src/libs/cplusplus/pp-environment.cpp b/src/libs/cplusplus/PreprocessorEnvironment.cpp similarity index 95% rename from src/libs/cplusplus/pp-environment.cpp rename to src/libs/cplusplus/PreprocessorEnvironment.cpp index 7b93c275d3d..693fe6160ea 100644 --- a/src/libs/cplusplus/pp-environment.cpp +++ b/src/libs/cplusplus/PreprocessorEnvironment.cpp @@ -50,16 +50,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "pp-environment.h" -#include "pp.h" - +#include "PreprocessorEnvironment.h" +#include "Macro.h" #include using namespace CPlusPlus; Environment::Environment() : currentLine(0), - hide_next(false), + hideNext(false), _macros(0), _allocated_macros(0), _macro_count(-1), @@ -94,7 +93,7 @@ Macro *Environment::bind(const Macro &__macro) Q_ASSERT(! __macro.name().isEmpty()); Macro *m = new Macro (__macro); - m->_hashcode = hash_code(m->name()); + m->_hashcode = hashCode(m->name()); if (++_macro_count == _allocated_macros) { if (! _allocated_macros) @@ -192,12 +191,12 @@ bool Environment::isBuiltinMacro(const QByteArray &s) const return false; } -Macro *Environment::resolve (const QByteArray &name) const +Macro *Environment::resolve(const QByteArray &name) const { if (! _macros) return 0; - Macro *it = _hash[hash_code (name) % _hash_count]; + Macro *it = _hash[hashCode(name) % _hash_count]; for (; it; it = it->_next) { if (it->name() != name) continue; @@ -208,7 +207,7 @@ Macro *Environment::resolve (const QByteArray &name) const return it; } -unsigned Environment::hash_code (const QByteArray &s) +unsigned Environment::hashCode(const QByteArray &s) { unsigned hash_value = 0; diff --git a/src/libs/cplusplus/pp-environment.h b/src/libs/cplusplus/PreprocessorEnvironment.h similarity index 97% rename from src/libs/cplusplus/pp-environment.h rename to src/libs/cplusplus/PreprocessorEnvironment.h index 97d0fe02d3c..48ee5b2715a 100644 --- a/src/libs/cplusplus/pp-environment.h +++ b/src/libs/cplusplus/PreprocessorEnvironment.h @@ -90,13 +90,13 @@ public: { return _macros + _macro_count + 1; } private: - static unsigned hash_code (const QByteArray &s); + static unsigned hashCode(const QByteArray &s); void rehash(); public: QByteArray currentFile; unsigned currentLine; - bool hide_next; + bool hideNext; private: Macro **_macros; diff --git a/src/libs/cplusplus/cplusplus.pro b/src/libs/cplusplus/cplusplus.pro index b8bde402825..f89d4d3f862 100644 --- a/src/libs/cplusplus/cplusplus.pro +++ b/src/libs/cplusplus/cplusplus.pro @@ -22,14 +22,14 @@ HEADERS += \ TypePrettyPrinter.h \ ResolveExpression.h \ LookupContext.h \ + PreprocessorClient.h \ + PreprocessorEnvironment.h \ + Macro.h \ pp.h \ pp-cctype.h \ pp-engine.h \ pp-macro-expander.h \ - pp-scanner.h \ - pp-client.h \ - pp-environment.h \ - pp-macro.h + pp-scanner.h SOURCES += \ SimpleLexer.cpp \ @@ -44,8 +44,10 @@ SOURCES += \ TypePrettyPrinter.cpp \ ResolveExpression.cpp \ LookupContext.cpp \ + PreprocessorClient.cpp \ + PreprocessorEnvironment.cpp \ + Macro.cpp \ pp-engine.cpp \ - pp-environment.cpp \ pp-macro-expander.cpp \ pp-scanner.cpp diff --git a/src/libs/cplusplus/pp-engine.h b/src/libs/cplusplus/pp-engine.h index 7ff0005c393..d0a573aed9c 100644 --- a/src/libs/cplusplus/pp-engine.h +++ b/src/libs/cplusplus/pp-engine.h @@ -53,7 +53,7 @@ #ifndef CPLUSPLUS_PP_ENGINE_H #define CPLUSPLUS_PP_ENGINE_H -#include "pp-client.h" +#include "PreprocessorClient.h" #include #include diff --git a/src/libs/cplusplus/pp-macro-expander.cpp b/src/libs/cplusplus/pp-macro-expander.cpp index 5b0f20b66c5..40bbc8090b6 100644 --- a/src/libs/cplusplus/pp-macro-expander.cpp +++ b/src/libs/cplusplus/pp-macro-expander.cpp @@ -213,12 +213,12 @@ const char *MacroExpander::operator () (const char *__first, const char *__last, } Macro *macro = env.resolve (fast_name); - if (! macro || macro->isHidden() || env.hide_next) + if (! macro || macro->isHidden() || env.hideNext) { if (fast_name.size () == 7 && fast_name [0] == 'd' && fast_name == "defined") - env.hide_next = true; + env.hideNext = true; else - env.hide_next = false; + env.hideNext = false; if (fast_name.size () == 8 && fast_name [0] == '_' && fast_name [1] == '_') { diff --git a/src/libs/cplusplus/pp.h b/src/libs/cplusplus/pp.h index 2cf40eed096..96c81867163 100644 --- a/src/libs/cplusplus/pp.h +++ b/src/libs/cplusplus/pp.h @@ -53,11 +53,11 @@ #ifndef CPLUSPLUS_PREPROCESSOR_H #define CPLUSPLUS_PREPROCESSOR_H -#include "pp-macro.h" -#include "pp-environment.h" +#include "Macro.h" +#include "PreprocessorClient.h" +#include "PreprocessorEnvironment.h" #include "pp-scanner.h" #include "pp-macro-expander.h" #include "pp-engine.h" -#include "pp-client.h" #endif // CPLUSPLUS_PREPROCESSOR_H From 0185a49a78100c544f273ac6f6a31fee393e7aba Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 23 Dec 2008 15:27:55 +0100 Subject: [PATCH 049/230] Removed LookupUtils. --- src/libs/cplusplus/LookupContext.cpp | 5 +---- src/libs/cplusplus/LookupContext.h | 16 +++------------- src/libs/cplusplus/TypeOfExpression.cpp | 1 + 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index ed70e5b2168..2b787a9e11c 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -44,10 +44,7 @@ using namespace CPlusPlus; -///////////////////////////////////////////////////////////////////// -// LookupUtils -///////////////////////////////////////////////////////////////////// -bool LookupUtils::isNameCompatibleWithIdentifier(Name *name, Identifier *id) +bool LookupContext::isNameCompatibleWithIdentifier(Name *name, Identifier *id) { if (! name) { return false; diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index 58d5baf439d..8759a79210e 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -34,22 +34,12 @@ #ifndef CPLUSPLUS_LOOKUPCONTEXT_H #define CPLUSPLUS_LOOKUPCONTEXT_H -#include #include - -#include -#include -#include +#include namespace CPlusPlus { -class CPLUSPLUS_EXPORT LookupUtils -{ -public: - static bool isNameCompatibleWithIdentifier(Name *name, Identifier *id); -}; - -class CPLUSPLUS_EXPORT LookupContext: LookupUtils +class CPLUSPLUS_EXPORT LookupContext { public: LookupContext(Control *control = 0); @@ -142,7 +132,7 @@ public: private: QList buildVisibleScopes(); - + static bool isNameCompatibleWithIdentifier(Name *name, Identifier *id); private: Control *_control; diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index 8c4ccb05e2f..7f08d5874d8 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -38,6 +38,7 @@ #include #include #include +#include using namespace CPlusPlus; From 5a966f8daea84e65ea5384b119f12016ac8ba8d2 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 29 Dec 2008 09:10:38 +0100 Subject: [PATCH 050/230] Test class specifiers with qualified names. --- .../auto/cplusplus/semantic/tst_semantic.cpp | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 30cbc73fc01..e36aba6cbc4 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -70,6 +70,7 @@ private slots: void function_declaration_1(); void function_declaration_2(); void function_definition_1(); + void nested_class_1(); }; void tst_Semantic::function_declaration_1() @@ -161,5 +162,51 @@ void tst_Semantic::function_definition_1() QCOMPARE(foo, QByteArray("foo")); } +void tst_Semantic::nested_class_1() +{ + QSharedPointer doc = document( +"class Object {\n" +" class Data;\n" +" Data *d;\n" +"};\n" +"class Object::Data {\n" +" Object *q;\n" +"};\n" + ); + QCOMPARE(doc->globals->symbolCount(), 2U); + + Class *classObject = doc->globals->symbolAt(0)->asClass(); + QVERIFY(classObject); + QVERIFY(classObject->name()); + NameId *classObjectNameId = classObject->name()->asNameId(); + QVERIFY(classObjectNameId); + Identifier *objectId = classObjectNameId->identifier(); + QCOMPARE(QByteArray(objectId->chars(), objectId->size()), QByteArray("Object")); + QCOMPARE(classObject->baseClassCount(), 0U); + QEXPECT_FAIL("", "Requires support for forward classes", Continue); + QCOMPARE(classObject->members()->symbolCount(), 2U); + + Class *classObjectData = doc->globals->symbolAt(1)->asClass(); + QVERIFY(classObjectData); + QVERIFY(classObjectData->name()); + QualifiedNameId *q = classObjectData->name()->asQualifiedNameId(); + QVERIFY(q); + QCOMPARE(q->nameCount(), 2U); + QVERIFY(q->nameAt(0)->asNameId()); + QVERIFY(q->nameAt(1)->asNameId()); + QCOMPARE(q->nameAt(0), classObject->name()); + QCOMPARE(doc->globals->lookat(q->nameAt(0)->asNameId()->identifier()), classObject); + + Declaration *decl = classObjectData->memberAt(0)->asDeclaration(); + QVERIFY(decl); + PointerType *ptrTy = decl->type()->asPointerType(); + QVERIFY(ptrTy); + NamedType *namedTy = ptrTy->elementType()->asNamedType(); + QVERIFY(namedTy); + QVERIFY(namedTy->name()->asNameId()); + QCOMPARE(namedTy->name()->asNameId()->identifier(), objectId); +} + + QTEST_APPLESS_MAIN(tst_Semantic) #include "tst_semantic.moc" From c9a5a2a26b6d42bb8d6270988f953e377c1fe584 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 29 Dec 2008 09:35:50 +0100 Subject: [PATCH 051/230] Added a simple DiagnosticClient to count the number of errors. --- .../auto/cplusplus/semantic/tst_semantic.cpp | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index e36aba6cbc4..09ed7c1c097 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -11,6 +11,7 @@ #include #include #include +#include CPLUSPLUS_USE_NAMESPACE @@ -21,6 +22,9 @@ class tst_Semantic: public QObject Control control; public: + tst_Semantic() + { control.setDiagnosticClient(&diag); } + TranslationUnit *parse(const QByteArray &source, TranslationUnit::ParseMode mode) { @@ -36,7 +40,7 @@ public: public: Document(TranslationUnit *unit) - : unit(unit), globals(new Scope()) + : unit(unit), globals(new Scope()), errorCount(0) { } ~Document() @@ -56,12 +60,32 @@ public: TranslationUnit *unit; Scope *globals; + unsigned errorCount; }; + class Diagnostic: public DiagnosticClient { + public: + int errorCount; + + Diagnostic() + : errorCount(0) + { } + + virtual void report(int, StringLiteral *, + unsigned, unsigned, + const char *, va_list) + { ++errorCount; } + }; + + Diagnostic diag; + + QSharedPointer document(const QByteArray &source) { + diag.errorCount = 0; // reset the error count. TranslationUnit *unit = parse(source, TranslationUnit::ParseTranlationUnit); QSharedPointer doc(new Document(unit)); + doc->errorCount = diag.errorCount; doc->check(); return doc; } @@ -76,6 +100,7 @@ private slots: void tst_Semantic::function_declaration_1() { QSharedPointer doc = document("void foo();"); + QCOMPARE(doc->errorCount, 0U); QCOMPARE(doc->globals->symbolCount(), 1U); Declaration *decl = doc->globals->symbolAt(0)->asDeclaration(); @@ -98,6 +123,7 @@ void tst_Semantic::function_declaration_1() void tst_Semantic::function_declaration_2() { QSharedPointer doc = document("void foo(const QString &s);"); + QCOMPARE(doc->errorCount, 0U); QCOMPARE(doc->globals->symbolCount(), 1U); Declaration *decl = doc->globals->symbolAt(0)->asDeclaration(); @@ -147,6 +173,7 @@ void tst_Semantic::function_declaration_2() void tst_Semantic::function_definition_1() { QSharedPointer doc = document("void foo() {}"); + QCOMPARE(doc->errorCount, 0U); QCOMPARE(doc->globals->symbolCount(), 1U); Function *funTy = doc->globals->symbolAt(0)->asFunction(); @@ -173,6 +200,7 @@ void tst_Semantic::nested_class_1() " Object *q;\n" "};\n" ); + QCOMPARE(doc->errorCount, 0U); QCOMPARE(doc->globals->symbolCount(), 2U); Class *classObject = doc->globals->symbolAt(0)->asClass(); @@ -207,6 +235,5 @@ void tst_Semantic::nested_class_1() QCOMPARE(namedTy->name()->asNameId()->identifier(), objectId); } - QTEST_APPLESS_MAIN(tst_Semantic) #include "tst_semantic.moc" From ccd05bd87eb1978bae6785548d804ae717874a83 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 29 Dec 2008 09:40:30 +0100 Subject: [PATCH 052/230] Added a simple test for anonymous structs and typedefs. --- .../auto/cplusplus/semantic/tst_semantic.cpp | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 09ed7c1c097..5a82429d54f 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -95,6 +95,7 @@ private slots: void function_declaration_2(); void function_definition_1(); void nested_class_1(); + void typedef_1(); }; void tst_Semantic::function_declaration_1() @@ -235,5 +236,33 @@ void tst_Semantic::nested_class_1() QCOMPARE(namedTy->name()->asNameId()->identifier(), objectId); } +void tst_Semantic::typedef_1() +{ + QSharedPointer doc = document( +"typedef struct {\n" +" int x, y;\n" +"} Point;\n" +"int main() {\n" +" Point pt;\n" +" pt.x = 1;\n" +"}\n" + ); + + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 3U); + + Class *anonStruct = doc->globals->symbolAt(0)->asClass(); + QVERIFY(anonStruct); + QCOMPARE(anonStruct->memberCount(), 2U); + + Declaration *typedefPointDecl = doc->globals->symbolAt(1)->asDeclaration(); + QVERIFY(typedefPointDecl); + QVERIFY(typedefPointDecl->isTypedef()); + QCOMPARE(typedefPointDecl->type()->asClass(), anonStruct); + + Function *mainFun = doc->globals->symbolAt(2)->asFunction(); + QVERIFY(mainFun); +} + QTEST_APPLESS_MAIN(tst_Semantic) #include "tst_semantic.moc" From 98cc3ec6c9ef0c1b47631c6d3a3ff8035e080249 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 29 Dec 2008 09:44:49 +0100 Subject: [PATCH 053/230] More testing of typedefs. --- .../auto/cplusplus/semantic/tst_semantic.cpp | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 5a82429d54f..ccc388e279a 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -96,6 +96,7 @@ private slots: void function_definition_1(); void nested_class_1(); void typedef_1(); + void typedef_2(); }; void tst_Semantic::function_declaration_1() @@ -264,5 +265,35 @@ void tst_Semantic::typedef_1() QVERIFY(mainFun); } +void tst_Semantic::typedef_2() +{ + QSharedPointer doc = document( +"struct _Point {\n" +" int x, y;\n" +"};\n" +"typedef _Point Point;\n" +"int main() {\n" +" Point pt;\n" +" pt.x = 1;\n" +"}\n" + ); + + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 3U); + + Class *_pointStruct= doc->globals->symbolAt(0)->asClass(); + QVERIFY(_pointStruct); + QCOMPARE(_pointStruct->memberCount(), 2U); + + Declaration *typedefPointDecl = doc->globals->symbolAt(1)->asDeclaration(); + QVERIFY(typedefPointDecl); + QVERIFY(typedefPointDecl->isTypedef()); + QVERIFY(typedefPointDecl->type()->isNamedType()); + QCOMPARE(typedefPointDecl->type()->asNamedType()->name(), _pointStruct->name()); + + Function *mainFun = doc->globals->symbolAt(2)->asFunction(); + QVERIFY(mainFun); +} + QTEST_APPLESS_MAIN(tst_Semantic) #include "tst_semantic.moc" From a985b59d402b189b90f5c15d291bc4fecd727d56 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 29 Dec 2008 11:53:40 +0100 Subject: [PATCH 054/230] Initial support for typedefs. --- src/libs/cplusplus/ResolveExpression.cpp | 66 ++++++++++++++++++++++ src/libs/cplusplus/ResolveExpression.h | 14 +++++ src/plugins/cpptools/cppcodecompletion.cpp | 22 ++++---- 3 files changed, 90 insertions(+), 12 deletions(-) diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 7ce0e42c69d..1f4dc9c51af 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -792,3 +792,69 @@ bool ResolveExpression::visit(PostIncrDecrAST *) { return false; } + +//////////////////////////////////////////////////////////////////////////////// +QList SymbolsForDotAccess::operator()(NamedType *namedTy, + ResolveExpression::Result p, + const LookupContext &context) +{ + QList resolvedSymbols; + + if (_blackList.contains(p)) + return resolvedSymbols; + + _blackList.append(p); + + const QList candidates = + context.resolve(namedTy->name(), context.visibleScopes(p)); + + foreach (Symbol *candidate, candidates) { + if (Class *klass = candidate->asClass()) { + if (resolvedSymbols.contains(klass)) + continue; // we already know about `klass' + resolvedSymbols.append(klass); + } else if (candidate->isTypedef()) { + if (Declaration *decl = candidate->asDeclaration()) { + if (Class *asClass = decl->type()->asClass()) { + // typedef struct { } Point; + // Point pt; + // pt. + resolvedSymbols.append(asClass); + } else { + // typedef Point Boh; + // Boh b; + // b. + const ResolveExpression::Result r(decl->type(), decl); + resolvedSymbols += operator()(r, context); + } + } + } else if (Declaration *decl = candidate->asDeclaration()) { + if (Function *funTy = decl->type()->asFunction()) { + // QString foo("ciao"); + // foo. + if (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope()) { + const ResolveExpression::Result r(funTy->returnType(), decl); + resolvedSymbols += operator()(r, context); + } + } + } + } + + return resolvedSymbols; +} + +QList SymbolsForDotAccess::operator()(ResolveExpression::Result p, + const LookupContext &context) +{ + FullySpecifiedType ty = p.first; + + if (NamedType *namedTy = ty->asNamedType()) { + return operator()(namedTy, p, context); + } else if (ReferenceType *refTy = ty->asReferenceType()) { + const ResolveExpression::Result e(refTy->elementType(), p.second); + return operator()(e, context); + } + + return QList(); +} + diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index ac4a675b459..35a32c84655 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -128,6 +128,20 @@ private: QList _results; }; +class CPLUSPLUS_EXPORT SymbolsForDotAccess +{ + QList _blackList; + +public: + QList operator()(NamedType *namedTy, + ResolveExpression::Result p, + const LookupContext &context); + + QList operator()(ResolveExpression::Result p, + const LookupContext &context); +}; + + } // end of namespace CPlusPlus #endif // CPLUSPLUS_RESOLVEEXPRESSION_H diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index f8c5fe9b48a..075a55b96e9 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -180,8 +180,6 @@ protected: } // namespace Internal } // namespace CppTools - - using namespace CppTools::Internal; FunctionArgumentWidget::FunctionArgumentWidget(Core::ICore *core) @@ -581,12 +579,12 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, const QList &results, const LookupContext &context) { - QTC_ASSERT(!results.isEmpty(), return false); + if (results.isEmpty()) + return false; + const TypeOfExpression::Result p = results.first(); QList classObjectCandidates; - TypeOfExpression::Result p = results.first(); - if (m_completionOperator == T_ARROW) { FullySpecifiedType ty = p.first; @@ -666,13 +664,13 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, } if (namedTy) { - const QList classes = - context.resolveClass(namedTy->name(), - context.visibleScopes(p)); - - foreach (Symbol *c, classes) { - if (! classObjectCandidates.contains(c)) - classObjectCandidates.append(c); + SymbolsForDotAccess symbolsForDotAccess; + const QList symbols = symbolsForDotAccess(namedTy, p, context); + foreach (Symbol *symbol, symbols) { + if (classObjectCandidates.contains(symbol)) + continue; + if (Class *klass = symbol->asClass()) + classObjectCandidates.append(klass); } } } From f02549dafe88b360f29f8c390d0e90b0e282f343 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 29 Dec 2008 12:26:02 +0100 Subject: [PATCH 055/230] Save/restore the black list so we can re-use instances of SymbolsForDotAccess. --- src/libs/cplusplus/ResolveExpression.cpp | 34 +++++++++++++++++++----- src/libs/cplusplus/ResolveExpression.h | 15 +++++++++-- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 1f4dc9c51af..a4d1de3afad 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -794,9 +794,31 @@ bool ResolveExpression::visit(PostIncrDecrAST *) } //////////////////////////////////////////////////////////////////////////////// +SymbolsForDotAccess::SymbolsForDotAccess() +{ } + QList SymbolsForDotAccess::operator()(NamedType *namedTy, ResolveExpression::Result p, const LookupContext &context) +{ + const QList previousBlackList = _blackList; + const QList symbols = symbolsForDotAccess(namedTy, p, context); + _blackList = previousBlackList; + return symbols; +} + +QList SymbolsForDotAccess::operator()(ResolveExpression::Result p, + const LookupContext &context) +{ + const QList previousBlackList = _blackList; + const QList symbols = symbolsForDotAccess(p, context); + _blackList = previousBlackList; + return symbols; +} + +QList SymbolsForDotAccess::symbolsForDotAccess(NamedType *namedTy, + ResolveExpression::Result p, + const LookupContext &context) { QList resolvedSymbols; @@ -825,7 +847,7 @@ QList SymbolsForDotAccess::operator()(NamedType *namedTy, // Boh b; // b. const ResolveExpression::Result r(decl->type(), decl); - resolvedSymbols += operator()(r, context); + resolvedSymbols += symbolsForDotAccess(r, context); } } } else if (Declaration *decl = candidate->asDeclaration()) { @@ -834,7 +856,7 @@ QList SymbolsForDotAccess::operator()(NamedType *namedTy, // foo. if (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope()) { const ResolveExpression::Result r(funTy->returnType(), decl); - resolvedSymbols += operator()(r, context); + resolvedSymbols += symbolsForDotAccess(r, context); } } } @@ -843,16 +865,16 @@ QList SymbolsForDotAccess::operator()(NamedType *namedTy, return resolvedSymbols; } -QList SymbolsForDotAccess::operator()(ResolveExpression::Result p, - const LookupContext &context) +QList SymbolsForDotAccess::symbolsForDotAccess(ResolveExpression::Result p, + const LookupContext &context) { FullySpecifiedType ty = p.first; if (NamedType *namedTy = ty->asNamedType()) { - return operator()(namedTy, p, context); + return symbolsForDotAccess(namedTy, p, context); } else if (ReferenceType *refTy = ty->asReferenceType()) { const ResolveExpression::Result e(refTy->elementType(), p.second); - return operator()(e, context); + return symbolsForDotAccess(e, context); } return QList(); diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index 35a32c84655..ff98b7344d7 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -130,15 +130,26 @@ private: class CPLUSPLUS_EXPORT SymbolsForDotAccess { - QList _blackList; - public: + SymbolsForDotAccess(); + QList operator()(NamedType *namedTy, ResolveExpression::Result p, const LookupContext &context); QList operator()(ResolveExpression::Result p, const LookupContext &context); + +private: + QList symbolsForDotAccess(NamedType *namedTy, + ResolveExpression::Result p, + const LookupContext &context); + + QList symbolsForDotAccess(ResolveExpression::Result p, + const LookupContext &context); + +private: + QList _blackList; }; From 5689826800f093f3c935bf75faa94683d344529a Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 13:20:09 +0100 Subject: [PATCH 056/230] get search right for qplaintextedit --- src/plugins/fakevim/handler.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 8c213c34c8e..78db71edc70 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -254,8 +254,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (m_submode == ZSubMode) { if (key == Key_Return) { - // cursor line to top of window, cursor on first non-blank - QRect rect = m_editor->cursorRect(); + // cursor line to top of window, cursor on first non-blank + QRect rect = m_editor->cursorRect(); int blocksUp = rect.y() / rect.height(); int blockNumber = m_tc.block().blockNumber(); QScrollBar *scrollBar = m_editor->verticalScrollBar(); @@ -265,7 +265,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } moveToFirstNonBlankOnLine(); finishMovement(); - } else { + } else { qDebug() << "Ignored z + " << key << text; } m_submode = NoSubMode; @@ -454,16 +454,18 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) void FakeVimHandler::Private::search(const QString &needle, bool backwards) { //qDebug() << "NEEDLE " << needle << "BACKWARDS" << backwards; - //int startPos = m_tc.position(); + QTextCursor orig = m_tc; QTextDocument::FindFlags flags; if (backwards) flags = QTextDocument::FindBackward; - m_tc.movePosition(backwards? Left : Right, MoveAnchor, 1); + if (!backwards) + m_tc.movePosition(Right, MoveAnchor, 1); + m_editor->setTextCursor(m_tc); if (m_editor->find(needle, flags)) { m_tc = m_editor->textCursor(); - m_tc.movePosition(Left, MoveAnchor, needle.size()); + m_tc.movePosition(Left, MoveAnchor, needle.size() - 1); return; } @@ -476,7 +478,7 @@ void FakeVimHandler::Private::search(const QString &needle, bool backwards) m_editor->setTextCursor(m_tc); if (m_editor->find(needle, flags)) { m_tc = m_editor->textCursor(); - m_tc.movePosition(Left, MoveAnchor, needle.size()); + m_tc.movePosition(Left, MoveAnchor, needle.size() - 1); if (backwards) showMessage("search hit TOP, continuing at BOTTOM"); else @@ -484,7 +486,7 @@ void FakeVimHandler::Private::search(const QString &needle, bool backwards) return; } - m_tc.movePosition(backwards ? Right : Left, MoveAnchor, 1); + m_tc = orig; } void FakeVimHandler::Private::moveToFirstNonBlankOnLine() From 21787ca4b5f07161ab5ade7eb2655165c827e498 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 16:27:47 +0100 Subject: [PATCH 057/230] handle PageUp, PageDown, Ctrl-F, Ctrl-B --- src/plugins/fakevim/handler.cpp | 54 ++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 78db71edc70..efbba597bf2 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -64,6 +64,7 @@ using namespace FakeVim::Internal; // FakeVimHandler // /////////////////////////////////////////////////////////////////////// + const int ParagraphSeparator = 0x00002029; using namespace Qt; @@ -110,6 +111,12 @@ public: int rightDist() const { return m_tc.block().length() - leftDist() - 1; } bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; } + // all zero-based counting + int cursorLineOnScreen() const; + int linesOnScreen() const; + int cursorLineInDocument() const; + void scrollToLineInDocument(int line); + void moveToFirstNonBlankOnLine(); FakeVimHandler *q; @@ -255,14 +262,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (m_submode == ZSubMode) { if (key == Key_Return) { // cursor line to top of window, cursor on first non-blank - QRect rect = m_editor->cursorRect(); - int blocksUp = rect.y() / rect.height(); - int blockNumber = m_tc.block().blockNumber(); - QScrollBar *scrollBar = m_editor->verticalScrollBar(); - if (blockNumber != blocksUp) { - scrollBar->setValue(scrollBar->value() * blockNumber - / (blockNumber - blocksUp)); - } + scrollToLineInDocument(cursorLineInDocument()); moveToFirstNonBlankOnLine(); finishMovement(); } else { @@ -380,6 +380,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key == 'z') { m_submode = ZSubMode; + } else if (key == Key_PageDown || key == control('f')) { + m_tc.movePosition(Down, KeepAnchor, count() * (linesOnScreen() - 2)); + finishMovement(); + } else if (key == Key_PageUp || key == control('b')) { + m_tc.movePosition(Up, KeepAnchor, count() * (linesOnScreen() - 2)); + finishMovement(); } else if (key == Key_Backspace) { m_tc.deletePreviousChar(); } else if (key == Key_Delete) { @@ -408,6 +414,12 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) m_tc.deletePreviousChar(); } else if (key == Key_Delete) { m_tc.deleteChar(); + } else if (key == Key_PageDown || key == control('f')) { + m_tc.movePosition(Down, KeepAnchor, count() * (linesOnScreen() - 2)); + finishMovement(); + } else if (key == Key_PageUp || key == control('b')) { + m_tc.movePosition(Up, KeepAnchor, count() * (linesOnScreen() - 2)); + finishMovement(); } else { m_tc.insertText(text); } @@ -503,6 +515,32 @@ void FakeVimHandler::Private::moveToFirstNonBlankOnLine() } } +int FakeVimHandler::Private::cursorLineOnScreen() const +{ + QRect rect = m_editor->cursorRect(); + return rect.y() / rect.height(); +} + +int FakeVimHandler::Private::linesOnScreen() const +{ + QRect rect = m_editor->cursorRect(); + //qDebug() << m_editor->height() / rect.height(); + return m_editor->height() / rect.height(); +} + +int FakeVimHandler::Private::cursorLineInDocument() const +{ + //qDebug() << "CURSOR LINE IN DOCUMENT " << m_tc.block().blockNumber(); + return m_tc.block().blockNumber(); +} + +void FakeVimHandler::Private::scrollToLineInDocument(int line) +{ + // FIXME: works only for QPlainTextEdit + QScrollBar *scrollBar = m_editor->verticalScrollBar(); + scrollBar->setValue(line); +} + /////////////////////////////////////////////////////////////////////// // // FakeVimHandler From 9e5e5d1d23d1130d7862d9315e673c6ea329fccd Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 19:11:21 +0100 Subject: [PATCH 058/230] partially implement 'w' and 'W' movement --- src/plugins/fakevim/handler.cpp | 49 +++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index efbba597bf2..0fe177cbc0d 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -111,6 +111,8 @@ public: int rightDist() const { return m_tc.block().length() - leftDist() - 1; } bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; } + int lastPositionInDocument() const; + // all zero-based counting int cursorLineOnScreen() const; int linesOnScreen() const; @@ -118,6 +120,7 @@ public: void scrollToLineInDocument(int line); void moveToFirstNonBlankOnLine(); + void moveWord(int repeat, bool simple); FakeVimHandler *q; Mode m_mode; @@ -366,6 +369,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_editor->redo(); } else if (key == 'u') { m_editor->undo(); + } else if (key == 'w') { + moveWord(count(), false); + finishMovement(); + } else if (key == 'W') { + moveWord(count(), true); + finishMovement(); } else if (key == 'x') { // = "dl" if (atEol()) m_tc.movePosition(Left, MoveAnchor, 1); @@ -481,12 +490,7 @@ void FakeVimHandler::Private::search(const QString &needle, bool backwards) return; } - int n = 0; - if (backwards) { - QTextBlock block = m_tc.block().document()->lastBlock(); - n = block.position() + block.length() - 1; - } - m_tc.setPosition(n); + m_tc.setPosition(backwards ? lastPositionInDocument() - 1 : 0); m_editor->setTextCursor(m_tc); if (m_editor->find(needle, flags)) { m_tc = m_editor->textCursor(); @@ -515,6 +519,33 @@ void FakeVimHandler::Private::moveToFirstNonBlankOnLine() } } +static int charClass(QChar c, bool simple) +{ + if (simple) + return c.isSpace() ? 0 : 1; + if (c.isLetterOrNumber() || c.unicode() == '_') + return 2; + return c.isSpace() ? 0 : 1; +} + +void FakeVimHandler::Private::moveWord(int repeat, bool simple) +{ + // FIXME: 'w' should stop on empty lines, too + QTextDocument *doc = m_tc.document(); + int n = lastPositionInDocument() - 1; + int lastClass = 0; + while (m_tc.position() < n) { + QChar c = doc->characterAt(m_tc.position()); + int thisClass = charClass(c, simple); + if (thisClass != lastClass && thisClass != 0) + --repeat; + if (repeat == -1) + break; + lastClass = thisClass; + m_tc.movePosition(Right, KeepAnchor, 1); + } +} + int FakeVimHandler::Private::cursorLineOnScreen() const { QRect rect = m_editor->cursorRect(); @@ -541,6 +572,12 @@ void FakeVimHandler::Private::scrollToLineInDocument(int line) scrollBar->setValue(line); } +int FakeVimHandler::Private::lastPositionInDocument() const +{ + QTextBlock block = m_tc.block().document()->lastBlock(); + return block.position() + block.length(); +} + /////////////////////////////////////////////////////////////////////// // // FakeVimHandler From eb132a4c375dd45c297ea35bc3ecf095bdc7af11 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 19:50:14 +0100 Subject: [PATCH 059/230] partial implementation of 'e' and 'E' --- src/plugins/fakevim/handler.cpp | 58 ++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 0fe177cbc0d..6c4ff474a60 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -120,7 +120,9 @@ public: void scrollToLineInDocument(int line); void moveToFirstNonBlankOnLine(); - void moveWord(int repeat, bool simple); + void moveToNextWord(int repeat, bool simple); + void moveToWordBegin(int repeat, bool simple); + void moveToWordEnd(int repeat, bool simple); FakeVimHandler *q; Mode m_mode; @@ -301,6 +303,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'A') { m_tc.movePosition(EndOfLine, MoveAnchor); m_mode = InsertMode; + } else if (key == 'b') { + moveToWordBegin(count(), false); + finishMovement(); + } else if (key == 'B') { + moveToWordBegin(count(), true); + finishMovement(); } else if (key == 'c') { m_submode = ChangeSubMode; } else if (key == 'C') { @@ -315,6 +323,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_submode = DeleteSubMode; m_tc.movePosition(EndOfLine, KeepAnchor); finishMovement(); + } else if (key == 'e') { + moveToWordEnd(count(), false); + finishMovement(); + } else if (key == 'E') { + moveToWordEnd(count(), true); + finishMovement(); } else if (key == 'h' || key == Key_Left) { int n = qMin(count(), leftDist()); if (m_fakeEnd && m_tc.block().length() > 1) @@ -370,10 +384,10 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'u') { m_editor->undo(); } else if (key == 'w') { - moveWord(count(), false); + moveToNextWord(count(), false); finishMovement(); } else if (key == 'W') { - moveWord(count(), true); + moveToNextWord(count(), true); finishMovement(); } else if (key == 'x') { // = "dl" if (atEol()) @@ -528,7 +542,43 @@ static int charClass(QChar c, bool simple) return c.isSpace() ? 0 : 1; } -void FakeVimHandler::Private::moveWord(int repeat, bool simple) +void FakeVimHandler::Private::moveToWordBegin(int repeat, bool simple) +{ + QTextDocument *doc = m_tc.document(); + int n = lastPositionInDocument() - 1; + int lastClass = 0; + while (m_tc.position() < n) { + QChar c = doc->characterAt(m_tc.position()); + int thisClass = charClass(c, simple); + if (thisClass != lastClass && thisClass != 0) + --repeat; + if (repeat == -1) + return; + lastClass = thisClass; + m_tc.movePosition(Right, KeepAnchor, 1); + } +} + +void FakeVimHandler::Private::moveToWordEnd(int repeat, bool simple) +{ + QTextDocument *doc = m_tc.document(); + int n = lastPositionInDocument() - 1; + int lastClass = 0; + while (m_tc.position() < n) { + QChar c = doc->characterAt(m_tc.position()); + int thisClass = charClass(c, simple); + if (thisClass != lastClass && lastClass != 0) + --repeat; + if (repeat == -1) { + m_tc.movePosition(Left, KeepAnchor, 1); + return; + } + lastClass = thisClass; + m_tc.movePosition(Right, KeepAnchor, 1); + } +} + +void FakeVimHandler::Private::moveToNextWord(int repeat, bool simple) { // FIXME: 'w' should stop on empty lines, too QTextDocument *doc = m_tc.document(); From 103876427f27a7fc62d6ddf7ecd0798070007f40 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 20:12:17 +0100 Subject: [PATCH 060/230] partially implement 'b' and 'B' --- src/plugins/fakevim/handler.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 6c4ff474a60..ef375b78e40 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -545,17 +545,20 @@ static int charClass(QChar c, bool simple) void FakeVimHandler::Private::moveToWordBegin(int repeat, bool simple) { QTextDocument *doc = m_tc.document(); - int n = lastPositionInDocument() - 1; int lastClass = 0; - while (m_tc.position() < n) { + while (true) { + m_tc.movePosition(Left, KeepAnchor, 1); QChar c = doc->characterAt(m_tc.position()); int thisClass = charClass(c, simple); - if (thisClass != lastClass && thisClass != 0) + if (thisClass != lastClass && lastClass != 0) --repeat; - if (repeat == -1) - return; + if (repeat == -1) { + m_tc.movePosition(Right, KeepAnchor, 1); + break; + } lastClass = thisClass; - m_tc.movePosition(Right, KeepAnchor, 1); + if (m_tc.position() == 0) + break; } } @@ -564,17 +567,19 @@ void FakeVimHandler::Private::moveToWordEnd(int repeat, bool simple) QTextDocument *doc = m_tc.document(); int n = lastPositionInDocument() - 1; int lastClass = 0; - while (m_tc.position() < n) { + while (true) { + m_tc.movePosition(Right, KeepAnchor, 1); QChar c = doc->characterAt(m_tc.position()); int thisClass = charClass(c, simple); if (thisClass != lastClass && lastClass != 0) --repeat; - if (repeat == -1) { + if (repeat == 0) { m_tc.movePosition(Left, KeepAnchor, 1); - return; + break; } lastClass = thisClass; - m_tc.movePosition(Right, KeepAnchor, 1); + if (m_tc.position() == n) + break; } } @@ -584,7 +589,7 @@ void FakeVimHandler::Private::moveToNextWord(int repeat, bool simple) QTextDocument *doc = m_tc.document(); int n = lastPositionInDocument() - 1; int lastClass = 0; - while (m_tc.position() < n) { + while (true) { QChar c = doc->characterAt(m_tc.position()); int thisClass = charClass(c, simple); if (thisClass != lastClass && thisClass != 0) @@ -593,6 +598,8 @@ void FakeVimHandler::Private::moveToNextWord(int repeat, bool simple) break; lastClass = thisClass; m_tc.movePosition(Right, KeepAnchor, 1); + if (m_tc.position() == n) + break; } } From 3ae02653632ec6d6ae61e2aae82c5ee3e1c6f0b2 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 22:22:41 +0100 Subject: [PATCH 061/230] implement plain ~ --- src/plugins/fakevim/handler.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index ef375b78e40..95971093824 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -403,6 +403,15 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key == 'z') { m_submode = ZSubMode; + } else if (key == '~') { + m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); + QString str = m_tc.selectedText(); + for (int i = str.size(); --i >= 0; ) { + QChar c = str.at(i); + str[i] = c.isUpper() ? c.toLower() : c.toUpper(); + } + m_tc.deleteChar(); + m_tc.insertText(str); } else if (key == Key_PageDown || key == control('f')) { m_tc.movePosition(Down, KeepAnchor, count() * (linesOnScreen() - 2)); finishMovement(); From fe261f0a90005773a65080fa934c011103c8c5f7 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 22:29:22 +0100 Subject: [PATCH 062/230] small fix for ~ at end of line --- src/plugins/fakevim/handler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 95971093824..8d6b4dd97d3 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -403,7 +403,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key == 'z') { m_submode = ZSubMode; - } else if (key == '~') { + } else if (key == '~' && !atEol()) { m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); QString str = m_tc.selectedText(); for (int i = str.size(); --i >= 0; ) { From 4d6b2905c483b982b77f45d84bc0d2ea89cdd0ad Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 22:41:09 +0100 Subject: [PATCH 063/230] get 3d2w right --- src/plugins/fakevim/handler.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 8d6b4dd97d3..b555ad76c49 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -106,7 +106,9 @@ public: void search(const QString &needle, bool backwards); void showMessage(const QString &msg); - int count() const { return m_count.isEmpty() ? 1 : m_count.toInt(); } + int mvCount() const { return m_mvcount.isEmpty() ? 1 : m_mvcount.toInt(); } + int opCount() const { return m_opcount.isEmpty() ? 1 : m_opcount.toInt(); } + int count() const { return mvCount() * opCount(); } int leftDist() const { return m_tc.position() - m_tc.block().position(); } int rightDist() const { return m_tc.block().length() - leftDist() - 1; } bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; } @@ -132,7 +134,8 @@ public: QTextCursor m_tc; QHash m_registers; int m_register; - QString m_count; + QString m_mvcount; + QString m_opcount; QStack m_undoStack; QStack m_redoStack; @@ -228,7 +231,8 @@ void FakeVimHandler::Private::finishMovement() if (atEol()) m_tc.movePosition(Left, MoveAnchor, 1); } - m_count.clear(); + m_mvcount.clear(); + m_opcount.clear(); m_register = '"'; m_tc.clearSelection(); updateCommandBuffer(); @@ -275,11 +279,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } m_submode = NoSubMode; } else if (key >= '0' && key <= '9') { - if (key == '0' && m_count.isEmpty()) { + if (key == '0' && m_mvcount.isEmpty()) { m_tc.movePosition(StartOfLine, KeepAnchor); finishMovement(); } else { - m_count.append(QChar(key)); + m_mvcount.append(QChar(key)); } } else if (key == ':' || key == '/' || key == '?') { m_commandCode = key; @@ -318,6 +322,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'd') { if (atEol()) m_tc.movePosition(Left, MoveAnchor, 1); + m_opcount = m_mvcount; + m_mvcount.clear(); m_submode = DeleteSubMode; } else if (key == 'D') { m_submode = DeleteSubMode; From 1e9214e1ddad8e723fbec595e80a634bcb026759 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 22:42:50 +0100 Subject: [PATCH 064/230] fix off-by-one for 'w' --- src/plugins/fakevim/handler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index b555ad76c49..8d029c8b49a 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -609,7 +609,7 @@ void FakeVimHandler::Private::moveToNextWord(int repeat, bool simple) int thisClass = charClass(c, simple); if (thisClass != lastClass && thisClass != 0) --repeat; - if (repeat == -1) + if (repeat == 0) break; lastClass = thisClass; m_tc.movePosition(Right, KeepAnchor, 1); From 5ac95bf8737d45f2b7b929f97e44d4746be2fe37 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 22:57:21 +0100 Subject: [PATCH 065/230] command mode + = command mode --- src/plugins/fakevim/handler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 8d029c8b49a..dbb9cc3f6b7 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -428,6 +428,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.deletePreviousChar(); } else if (key == Key_Delete) { m_tc.deleteChar(); + } else if (key == Key_Escape) { + // harmless } else { qDebug() << "Ignored" << key << text; } From 0a665de576e2a4da2ff47ebe10e58295ec574cd1 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Dec 2008 23:19:08 +0100 Subject: [PATCH 066/230] initialize commandCode --- src/plugins/fakevim/handler.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index dbb9cc3f6b7..e1540c9f511 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -153,6 +153,7 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) { q = parent; m_mode = CommandMode; + m_commandCode = 0; m_fakeEnd = false; m_lastSearchBackward = false; m_register = '"'; @@ -240,7 +241,6 @@ void FakeVimHandler::Private::finishMovement() void FakeVimHandler::Private::updateCommandBuffer() { - //qDebug() << "CMD" << m_commandBuffer; QString msg = QChar(m_commandCode ? m_commandCode : ' ') + m_commandBuffer; emit q->commandBufferChanged(msg); } @@ -605,9 +605,10 @@ void FakeVimHandler::Private::moveToNextWord(int repeat, bool simple) // FIXME: 'w' should stop on empty lines, too QTextDocument *doc = m_tc.document(); int n = lastPositionInDocument() - 1; - int lastClass = 0; + QChar c = doc->characterAt(m_tc.position()); + int lastClass = charClass(c, simple); while (true) { - QChar c = doc->characterAt(m_tc.position()); + c = doc->characterAt(m_tc.position()); int thisClass = charClass(c, simple); if (thisClass != lastClass && thisClass != 0) --repeat; From d0f17e7568cbf4749e1dec9c738a2177f2a3bfec Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 26 Dec 2008 00:18:03 +0100 Subject: [PATCH 067/230] start implementing 'f', 'F', 't', 'T' --- src/plugins/fakevim/handler.cpp | 120 +++++++++++++++++++++----------- 1 file changed, 78 insertions(+), 42 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index e1540c9f511..d277fc02624 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -85,6 +85,12 @@ enum SubMode ZSubMode }; +enum SubSubMode +{ + NoSubSubMode, + FtSubSubMode, // used for f, F, t, T +}; + class FakeVimHandler::Private { public: @@ -103,7 +109,7 @@ public: void handleExMode(int key, const QString &text); void finishMovement(); void updateCommandBuffer(); - void search(const QString &needle, bool backwards); + void search(const QString &needle, bool forward); void showMessage(const QString &msg); int mvCount() const { return m_mvcount.isEmpty() ? 1 : m_mvcount.toInt(); } @@ -122,13 +128,15 @@ public: void scrollToLineInDocument(int line); void moveToFirstNonBlankOnLine(); - void moveToNextWord(int repeat, bool simple); - void moveToWordBegin(int repeat, bool simple); - void moveToWordEnd(int repeat, bool simple); + void moveToNextWord(bool simple); + void moveToWordBoundary(bool simple, bool forward); + void handleFfTt(int key); FakeVimHandler *q; Mode m_mode; SubMode m_submode; + SubSubMode m_subsubmode; + int m_subsubdata; QString m_input; QPlainTextEdit *m_editor; QTextCursor m_tc; @@ -153,6 +161,8 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) { q = parent; m_mode = CommandMode; + m_submode = NoSubMode; + m_subsubmode = NoSubSubMode; m_commandCode = 0; m_fakeEnd = false; m_lastSearchBackward = false; @@ -278,6 +288,10 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) qDebug() << "Ignored z + " << key << text; } m_submode = NoSubMode; + } else if (m_subsubmode == FtSubSubMode) { + handleFfTt(key); + m_subsubmode = NoSubSubMode; + finishMovement(); } else if (key >= '0' && key <= '9') { if (key == '0' && m_mvcount.isEmpty()) { m_tc.movePosition(StartOfLine, KeepAnchor); @@ -308,10 +322,10 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(EndOfLine, MoveAnchor); m_mode = InsertMode; } else if (key == 'b') { - moveToWordBegin(count(), false); + moveToWordBoundary(false, false); finishMovement(); } else if (key == 'B') { - moveToWordBegin(count(), true); + moveToWordBoundary(true, false); finishMovement(); } else if (key == 'c') { m_submode = ChangeSubMode; @@ -330,11 +344,14 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(EndOfLine, KeepAnchor); finishMovement(); } else if (key == 'e') { - moveToWordEnd(count(), false); + moveToWordBoundary(false, true); finishMovement(); } else if (key == 'E') { - moveToWordEnd(count(), true); + moveToWordBoundary(true, true); finishMovement(); + } else if (key == 'f' || key == 'F') { + m_subsubmode = FtSubSubMode; + m_subsubdata = key; } else if (key == 'h' || key == Key_Left) { int n = qMin(count(), leftDist()); if (m_fakeEnd && m_tc.block().length() > 1) @@ -387,13 +404,16 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } } else if (key == control('r')) { m_editor->redo(); + } else if (key == 't' || key == 'T') { + m_subsubmode = FtSubSubMode; + m_subsubdata = key; } else if (key == 'u') { m_editor->undo(); } else if (key == 'w') { - moveToNextWord(count(), false); + moveToNextWord(false); finishMovement(); } else if (key == 'W') { - moveToNextWord(count(), true); + moveToNextWord(true); finishMovement(); } else if (key == 'x') { // = "dl" if (atEol()) @@ -503,15 +523,15 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) updateCommandBuffer(); } -void FakeVimHandler::Private::search(const QString &needle, bool backwards) +void FakeVimHandler::Private::search(const QString &needle, bool forward) { //qDebug() << "NEEDLE " << needle << "BACKWARDS" << backwards; QTextCursor orig = m_tc; QTextDocument::FindFlags flags; - if (backwards) + if (!forward) flags = QTextDocument::FindBackward; - if (!backwards) + if (forward) m_tc.movePosition(Right, MoveAnchor, 1); m_editor->setTextCursor(m_tc); @@ -521,15 +541,15 @@ void FakeVimHandler::Private::search(const QString &needle, bool backwards) return; } - m_tc.setPosition(backwards ? lastPositionInDocument() - 1 : 0); + m_tc.setPosition(forward ? 0 : lastPositionInDocument() - 1); m_editor->setTextCursor(m_tc); if (m_editor->find(needle, flags)) { m_tc = m_editor->textCursor(); m_tc.movePosition(Left, MoveAnchor, needle.size() - 1); - if (backwards) - showMessage("search hit TOP, continuing at BOTTOM"); - else + if (forward) showMessage("search hit BOTTOM, continuing at TOP"); + else + showMessage("search hit TOP, continuing at BOTTOM"); return; } @@ -559,39 +579,20 @@ static int charClass(QChar c, bool simple) return c.isSpace() ? 0 : 1; } -void FakeVimHandler::Private::moveToWordBegin(int repeat, bool simple) +void FakeVimHandler::Private::moveToWordBoundary(bool simple, bool forward) { + int repeat = count(); QTextDocument *doc = m_tc.document(); + int n = forward ? lastPositionInDocument() - 1 : 0; int lastClass = 0; while (true) { - m_tc.movePosition(Left, KeepAnchor, 1); + m_tc.movePosition(forward ? Right : Left, KeepAnchor, 1); QChar c = doc->characterAt(m_tc.position()); int thisClass = charClass(c, simple); if (thisClass != lastClass && lastClass != 0) --repeat; if (repeat == -1) { - m_tc.movePosition(Right, KeepAnchor, 1); - break; - } - lastClass = thisClass; - if (m_tc.position() == 0) - break; - } -} - -void FakeVimHandler::Private::moveToWordEnd(int repeat, bool simple) -{ - QTextDocument *doc = m_tc.document(); - int n = lastPositionInDocument() - 1; - int lastClass = 0; - while (true) { - m_tc.movePosition(Right, KeepAnchor, 1); - QChar c = doc->characterAt(m_tc.position()); - int thisClass = charClass(c, simple); - if (thisClass != lastClass && lastClass != 0) - --repeat; - if (repeat == 0) { - m_tc.movePosition(Left, KeepAnchor, 1); + m_tc.movePosition(forward ? Left : Right, KeepAnchor, 1); break; } lastClass = thisClass; @@ -600,9 +601,44 @@ void FakeVimHandler::Private::moveToWordEnd(int repeat, bool simple) } } -void FakeVimHandler::Private::moveToNextWord(int repeat, bool simple) +void FakeVimHandler::Private::handleFfTt(int key) +{ + // m_subsubmode \in { 'f', 'F', 't', 'T' } + bool forward = m_subsubdata == 'f' || m_subsubdata == 't'; + int repeat = count(); + QTextDocument *doc = m_tc.document(); + QTextBlock block = m_tc.block(); + int n = block.position(); + if (forward) + n += block.length(); + int pos = m_tc.position(); + while (true) { + pos += forward ? 1 : -1; + if (pos == n) + break; + int uc = doc->characterAt(pos).unicode(); + if (uc == ParagraphSeparator) + break; + if (uc == key) + --repeat; + if (repeat == 0) { + if (m_subsubdata == 't') + --pos; + if (m_subsubdata == 'T') + ++pos; + if (forward) + m_tc.movePosition(Right, KeepAnchor, pos - m_tc.position()); + else + m_tc.movePosition(Left, KeepAnchor, m_tc.position() - pos); + break; + } + } +} + +void FakeVimHandler::Private::moveToNextWord(bool simple) { // FIXME: 'w' should stop on empty lines, too + int repeat = count(); QTextDocument *doc = m_tc.document(); int n = lastPositionInDocument() - 1; QChar c = doc->characterAt(m_tc.position()); From 84af25f689f5b8f703c00e5d9563565ad039994c Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 26 Dec 2008 00:25:38 +0100 Subject: [PATCH 068/230] small correction for 'df' --- src/plugins/fakevim/handler.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index d277fc02624..a3eef93f96d 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -624,8 +624,14 @@ void FakeVimHandler::Private::handleFfTt(int key) if (repeat == 0) { if (m_subsubdata == 't') --pos; - if (m_subsubdata == 'T') + else if (m_subsubdata == 'T') ++pos; + // FIXME: strange correction... + if (m_submode == DeleteSubMode && m_subsubdata == 'f') + ++pos; + if (m_submode == DeleteSubMode && m_subsubdata == 't') + ++pos; + if (forward) m_tc.movePosition(Right, KeepAnchor, pos - m_tc.position()); else From 8b663b35b25f75f84f3c1b736d64207231e1dd7d Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 26 Dec 2008 00:29:51 +0100 Subject: [PATCH 069/230] fix recently introduced backward/forward mess for searching --- src/plugins/fakevim/handler.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index a3eef93f96d..e19d7b74187 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -153,7 +153,7 @@ public: int m_commandCode; // ?, /, : ... QString m_commandBuffer; - bool m_lastSearchBackward; + bool m_lastSearchForward; QString m_lastSearchString; }; @@ -165,7 +165,7 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) m_subsubmode = NoSubSubMode; m_commandCode = 0; m_fakeEnd = false; - m_lastSearchBackward = false; + m_lastSearchForward = true; m_register = '"'; } @@ -386,9 +386,9 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) moveToFirstNonBlankOnLine(); finishMovement(); } else if (key == 'n') { - search(m_lastSearchString, m_lastSearchBackward); + search(m_lastSearchString, m_lastSearchForward); } else if (key == 'N') { - search(m_lastSearchString, !m_lastSearchBackward); + search(m_lastSearchString, !m_lastSearchForward); } else if (key == 'p') { QString text = m_registers[m_register]; int n = text.count(QChar(ParagraphSeparator)); @@ -511,9 +511,9 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_mode = CommandMode; } else if (key == Key_Return && (m_commandCode == '/' || m_commandCode == '?')) { - m_lastSearchBackward = (m_commandCode == '?'); + m_lastSearchForward = (m_commandCode == '/'); m_lastSearchString = m_commandBuffer; - search(m_lastSearchString, m_lastSearchBackward); + search(m_lastSearchString, m_lastSearchForward); m_commandBuffer.clear(); m_commandCode = 0; m_mode = CommandMode; From 685162aa9c2c5132e5979d78c6ab673cf1829589 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 26 Dec 2008 00:45:40 +0100 Subject: [PATCH 070/230] fix D and EOL behaviour --- src/plugins/fakevim/handler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index e19d7b74187..6a386b02864 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -341,7 +341,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_submode = DeleteSubMode; } else if (key == 'D') { m_submode = DeleteSubMode; - m_tc.movePosition(EndOfLine, KeepAnchor); + m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0)); + m_tc.movePosition(Right, KeepAnchor, rightDist()); finishMovement(); } else if (key == 'e') { moveToWordBoundary(false, true); From 8e5b3a260c4b75b3c3d2f1b1c9761895888dd9c9 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 26 Dec 2008 13:39:47 +0100 Subject: [PATCH 071/230] mention QList in list of available dumpers --- bin/gdbmacros/gdbmacros.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp index c58e83abf01..04a04abf8f7 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -2452,6 +2452,7 @@ void qDumpObjectData440( "\""NS"QHash\"," "\""NS"QHashNode\"," "\""NS"QImage\"," + "\""NS"QList\"," "\""NS"QLocale\"," "\""NS"QMap\"," "\""NS"QMapNode\"," From 40886db56ff1d2fa5a4fd2942a9e71edab921468 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 26 Dec 2008 17:01:21 +0100 Subject: [PATCH 072/230] add history of search strings --- src/plugins/fakevim/handler.cpp | 54 +++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 6a386b02864..fc927ea99e8 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -150,11 +150,22 @@ public: bool m_fakeEnd; + bool isSearchCommand() const + { return m_commandCode == '?' || m_commandCode == '/'; } int m_commandCode; // ?, /, : ... + QString m_commandBuffer; bool m_lastSearchForward; - QString m_lastSearchString; + + // History for '/' + QString lastSearchString() const; + QStringList m_searchHistory; + int m_searchHistoryIndex; + + // History for ':' + QStringList m_commandHistory; + int m_commandHistoryIndex; }; FakeVimHandler::Private::Private(FakeVimHandler *parent) @@ -302,6 +313,13 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == ':' || key == '/' || key == '?') { m_commandCode = key; m_mode = ExMode; + if (isSearchCommand()) { + m_searchHistory.append(QString()); + m_searchHistoryIndex = m_searchHistory.size() - 1; + } else { + m_commandHistory.append(QString()); + m_commandHistoryIndex = m_commandHistory.size() - 1; + } updateCommandBuffer(); } else if (key == '|') { m_tc.movePosition(StartOfLine, KeepAnchor); @@ -387,9 +405,9 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) moveToFirstNonBlankOnLine(); finishMovement(); } else if (key == 'n') { - search(m_lastSearchString, m_lastSearchForward); + search(lastSearchString(), m_lastSearchForward); } else if (key == 'N') { - search(m_lastSearchString, !m_lastSearchForward); + search(lastSearchString(), !m_lastSearchForward); } else if (key == 'p') { QString text = m_registers[m_register]; int n = text.count(QChar(ParagraphSeparator)); @@ -510,14 +528,23 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) } m_commandBuffer.clear(); m_mode = CommandMode; - } else if (key == Key_Return - && (m_commandCode == '/' || m_commandCode == '?')) { + } else if (key == Key_Return && isSearchCommand()) { m_lastSearchForward = (m_commandCode == '/'); - m_lastSearchString = m_commandBuffer; - search(m_lastSearchString, m_lastSearchForward); + m_searchHistory.append(m_commandBuffer); + search(lastSearchString(), m_lastSearchForward); m_commandBuffer.clear(); m_commandCode = 0; m_mode = CommandMode; + } else if (key == Key_Up && isSearchCommand()) { + if (m_searchHistoryIndex > 0) { + --m_searchHistoryIndex; + m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); + } + } else if (key == Key_Down && isSearchCommand()) { + if (m_searchHistoryIndex < m_searchHistory.size() - 1) { + ++m_searchHistoryIndex; + m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); + } } else { m_commandBuffer += QChar(key); } @@ -528,7 +555,7 @@ void FakeVimHandler::Private::search(const QString &needle, bool forward) { //qDebug() << "NEEDLE " << needle << "BACKWARDS" << backwards; QTextCursor orig = m_tc; - QTextDocument::FindFlags flags; + QTextDocument::FindFlags flags = QTextDocument::FindCaseSensitively; if (!forward) flags = QTextDocument::FindBackward; @@ -538,7 +565,8 @@ void FakeVimHandler::Private::search(const QString &needle, bool forward) m_editor->setTextCursor(m_tc); if (m_editor->find(needle, flags)) { m_tc = m_editor->textCursor(); - m_tc.movePosition(Left, MoveAnchor, needle.size() - 1); + // the qMax seems to be needed for QPlainTextEdit only + m_tc.movePosition(Left, MoveAnchor, qMax(1, needle.size() - 1)); return; } @@ -546,7 +574,8 @@ void FakeVimHandler::Private::search(const QString &needle, bool forward) m_editor->setTextCursor(m_tc); if (m_editor->find(needle, flags)) { m_tc = m_editor->textCursor(); - m_tc.movePosition(Left, MoveAnchor, needle.size() - 1); + // the qMax seems to be needed for QPlainTextEdit only + m_tc.movePosition(Left, MoveAnchor, qMax(1, needle.size() - 1)); if (forward) showMessage("search hit BOTTOM, continuing at TOP"); else @@ -696,6 +725,11 @@ int FakeVimHandler::Private::lastPositionInDocument() const return block.position() + block.length(); } +QString FakeVimHandler::Private::lastSearchString() const +{ + return m_searchHistory.empty() ? QString() : m_searchHistory.back(); +} + /////////////////////////////////////////////////////////////////////// // // FakeVimHandler From bfa828ef9d2eb3978ced55dfe34f3cade14c8a33 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 26 Dec 2008 18:29:38 +0100 Subject: [PATCH 073/230] Make it work for both QTextEdit and QPlainTextEdit. Scrolling is broken for plain QTextEdit. --- src/plugins/fakevim/handler.cpp | 72 ++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index fc927ea99e8..01808c1a51b 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -50,13 +50,13 @@ using namespace FakeVim::Internal; #define StartOfLine QTextCursor::StartOfLine -#define EndOfLine QTextCursor::EndOfLine -#define MoveAnchor QTextCursor::MoveAnchor -#define KeepAnchor QTextCursor::KeepAnchor -#define Up QTextCursor::Up -#define Down QTextCursor::Down -#define Right QTextCursor::Right -#define Left QTextCursor::Left +#define EndOfLine QTextCursor::EndOfLine +#define MoveAnchor QTextCursor::MoveAnchor +#define KeepAnchor QTextCursor::KeepAnchor +#define Up QTextCursor::Up +#define Down QTextCursor::Down +#define Right QTextCursor::Right +#define Left QTextCursor::Left /////////////////////////////////////////////////////////////////////// @@ -65,6 +65,8 @@ using namespace FakeVim::Internal; // /////////////////////////////////////////////////////////////////////// +#define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s) + const int ParagraphSeparator = 0x00002029; using namespace Qt; @@ -138,7 +140,8 @@ public: SubSubMode m_subsubmode; int m_subsubdata; QString m_input; - QPlainTextEdit *m_editor; + QTextEdit *m_textedit; + QPlainTextEdit *m_plaintextedit; QTextCursor m_tc; QHash m_registers; int m_register; @@ -190,11 +193,13 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) //qDebug() << "KEY: " << key << Qt::ShiftModifier; // Fake "End of line" - m_editor = qobject_cast(ob); - if (!m_editor) + m_textedit = qobject_cast(ob); + m_plaintextedit = qobject_cast(ob); + if (!m_textedit && !m_plaintextedit) return false; - m_tc = m_editor->textCursor(); + m_tc = EDITOR(textCursor()); + if (m_fakeEnd) { //m_fakeEnd = false; m_tc.movePosition(Right, MoveAnchor, 1); @@ -224,8 +229,8 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) // << " BLOCK LEN: " << m_tc.block().length() // << " LEFT: " << leftDist() << " RIGHT: " << rightDist(); - m_editor->setTextCursor(m_tc); - m_editor->ensureCursorVisible(); + EDITOR(setTextCursor(m_tc)); + EDITOR(ensureCursorVisible()); return true; } @@ -378,7 +383,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(Left, KeepAnchor, n); finishMovement(); } else if (key == 'H') { - m_tc = m_editor->cursorForPosition(QPoint(0, 0)); + m_tc = EDITOR(cursorForPosition(QPoint(0, 0))); m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0)); moveToFirstNonBlankOnLine(); finishMovement(); @@ -394,14 +399,14 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); finishMovement(); } else if (key == 'L') { - int heigth = m_editor->height(); - m_tc = m_editor->cursorForPosition(QPoint(0, heigth)); + int heigth = EDITOR(height()); + m_tc = EDITOR(cursorForPosition(QPoint(0, heigth))); m_tc.movePosition(Up, KeepAnchor, qMax(count(), 1)); moveToFirstNonBlankOnLine(); finishMovement(); } else if (key == 'M') { - int heigth = m_editor->height(); - m_tc = m_editor->cursorForPosition(QPoint(0, heigth / 2)); + int heigth = EDITOR(height()); + m_tc = EDITOR(cursorForPosition(QPoint(0, heigth / 2))); moveToFirstNonBlankOnLine(); finishMovement(); } else if (key == 'n') { @@ -422,12 +427,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(Left); } } else if (key == control('r')) { - m_editor->redo(); + EDITOR(redo()); } else if (key == 't' || key == 'T') { m_subsubmode = FtSubSubMode; m_subsubdata = key; } else if (key == 'u') { - m_editor->undo(); + EDITOR(undo()); } else if (key == 'w') { moveToNextWord(false); finishMovement(); @@ -524,7 +529,10 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_tc.setPosition(m_tc.block().document() ->findBlockByNumber(n - 1).position()); } else if (m_commandBuffer == "q!" || m_commandBuffer == "q") { - q->quitRequested(m_editor); + if (m_textedit) + q->quitRequested(m_textedit); + else + q->quitRequested(m_plaintextedit); } m_commandBuffer.clear(); m_mode = CommandMode; @@ -562,18 +570,18 @@ void FakeVimHandler::Private::search(const QString &needle, bool forward) if (forward) m_tc.movePosition(Right, MoveAnchor, 1); - m_editor->setTextCursor(m_tc); - if (m_editor->find(needle, flags)) { - m_tc = m_editor->textCursor(); + EDITOR(setTextCursor(m_tc)); + if (EDITOR(find(needle, flags))) { + m_tc = EDITOR(textCursor()); // the qMax seems to be needed for QPlainTextEdit only m_tc.movePosition(Left, MoveAnchor, qMax(1, needle.size() - 1)); return; } m_tc.setPosition(forward ? 0 : lastPositionInDocument() - 1); - m_editor->setTextCursor(m_tc); - if (m_editor->find(needle, flags)) { - m_tc = m_editor->textCursor(); + EDITOR(setTextCursor(m_tc)); + if (EDITOR(find(needle, flags))) { + m_tc = EDITOR(textCursor()); // the qMax seems to be needed for QPlainTextEdit only m_tc.movePosition(Left, MoveAnchor, qMax(1, needle.size() - 1)); if (forward) @@ -695,15 +703,15 @@ void FakeVimHandler::Private::moveToNextWord(bool simple) int FakeVimHandler::Private::cursorLineOnScreen() const { - QRect rect = m_editor->cursorRect(); + QRect rect = EDITOR(cursorRect()); return rect.y() / rect.height(); } int FakeVimHandler::Private::linesOnScreen() const { - QRect rect = m_editor->cursorRect(); - //qDebug() << m_editor->height() / rect.height(); - return m_editor->height() / rect.height(); + QRect rect = EDITOR(cursorRect()); + //qDebug() << EDITOR(height()) / rect.height(); + return EDITOR(height()) / rect.height(); } int FakeVimHandler::Private::cursorLineInDocument() const @@ -715,7 +723,7 @@ int FakeVimHandler::Private::cursorLineInDocument() const void FakeVimHandler::Private::scrollToLineInDocument(int line) { // FIXME: works only for QPlainTextEdit - QScrollBar *scrollBar = m_editor->verticalScrollBar(); + QScrollBar *scrollBar = EDITOR(verticalScrollBar()); scrollBar->setValue(line); } From eeffd9beb078a3cce8226ed1d79fb70f266e3a47 Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 12:24:50 +0100 Subject: [PATCH 074/230] make work for 'i' --- src/plugins/fakevim/handler.cpp | 18 +++++++++++- tests/auto/fakevim/fakevim.pro | 9 ++++++ tests/auto/fakevim/main.cpp | 49 +++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 tests/auto/fakevim/fakevim.pro create mode 100644 tests/auto/fakevim/main.cpp diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 01808c1a51b..cb2bba2b8b8 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -160,6 +160,7 @@ public: QString m_commandBuffer; bool m_lastSearchForward; + QString m_lastInsertion; // History for '/' QString lastSearchString() const; @@ -388,6 +389,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) moveToFirstNonBlankOnLine(); finishMovement(); } else if (key == 'i') { + m_lastInsertion.clear(); m_mode = InsertMode; } else if (key == 'j' || key == Key_Down) { m_tc.movePosition(Down, KeepAnchor, count()); @@ -483,28 +485,42 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) { if (key == Key_Escape) { m_mode = CommandMode; - m_tc.movePosition(Left, KeepAnchor, qMin(1, leftDist())); + for (int i = 1; i < count(); ++i) + m_tc.insertText(m_lastInsertion); + m_tc.movePosition(Left, MoveAnchor, qMin(1, leftDist())); } else if (key == Key_Left) { m_tc.movePosition(Left, MoveAnchor, 1); + m_lastInsertion.clear(); } else if (key == Key_Down) { m_tc.movePosition(Down, MoveAnchor, 1); + m_lastInsertion.clear(); } else if (key == Key_Up) { m_tc.movePosition(Up, MoveAnchor, 1); + m_lastInsertion.clear(); } else if (key == Key_Right) { m_tc.movePosition(Right, MoveAnchor, 1); + m_lastInsertion.clear(); } else if (key == Key_Return) { m_tc.insertBlock(); + m_lastInsertion.clear(); } else if (key == Key_Backspace) { m_tc.deletePreviousChar(); + m_lastInsertion = m_lastInsertion.left(m_lastInsertion.size() - 1); } else if (key == Key_Delete) { m_tc.deleteChar(); + m_lastInsertion.clear(); } else if (key == Key_PageDown || key == control('f')) { m_tc.movePosition(Down, KeepAnchor, count() * (linesOnScreen() - 2)); + m_lastInsertion.clear(); + } else if (key == Key_Backspace) { finishMovement(); } else if (key == Key_PageUp || key == control('b')) { m_tc.movePosition(Up, KeepAnchor, count() * (linesOnScreen() - 2)); + m_lastInsertion.clear(); + } else if (key == Key_Backspace) { finishMovement(); } else { + m_lastInsertion.append(text); m_tc.insertText(text); } } diff --git a/tests/auto/fakevim/fakevim.pro b/tests/auto/fakevim/fakevim.pro new file mode 100644 index 00000000000..696feeec31c --- /dev/null +++ b/tests/auto/fakevim/fakevim.pro @@ -0,0 +1,9 @@ + +load(qttest_p4) + +SOURCES += \ + main.cpp \ + handler.cpp + +HEADER += \ + handler.h diff --git a/tests/auto/fakevim/main.cpp b/tests/auto/fakevim/main.cpp new file mode 100644 index 00000000000..28a05dcd530 --- /dev/null +++ b/tests/auto/fakevim/main.cpp @@ -0,0 +1,49 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ + +#include "handler.h" + +#include +#include + +class tst_FakeVim : public QObject +{ + Q_OBJECT + +private slots: +}; + + +QTEST_MAIN(tst_FakeVim) + +#include "main.moc" From b748b12d03a39893beb2aba86809d274b4737a28 Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 13:39:34 +0100 Subject: [PATCH 075/230] basic support for 'J' --- src/plugins/fakevim/handler.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index cb2bba2b8b8..7bdd92f3e1d 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -156,6 +156,7 @@ public: bool isSearchCommand() const { return m_commandCode == '?' || m_commandCode == '/'; } int m_commandCode; // ?, /, : ... + int m_gflag; // whether current command started with 'g' QString m_commandBuffer; @@ -182,6 +183,7 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) m_fakeEnd = false; m_lastSearchForward = true; m_register = '"'; + m_gflag = false; } bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) @@ -261,6 +263,7 @@ void FakeVimHandler::Private::finishMovement() } m_mvcount.clear(); m_opcount.clear(); + m_gflag = false; m_register = '"'; m_tc.clearSelection(); updateCommandBuffer(); @@ -377,6 +380,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'f' || key == 'F') { m_subsubmode = FtSubSubMode; m_subsubdata = key; + } else if (key == 'g') { + m_gflag = true; } else if (key == 'h' || key == Key_Left) { int n = qMin(count(), leftDist()); if (m_fakeEnd && m_tc.block().length() > 1) @@ -394,6 +399,15 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'j' || key == Key_Down) { m_tc.movePosition(Down, KeepAnchor, count()); finishMovement(); + } else if (key == 'J') { + if (m_submode == NoSubMode) { + for (int i = qMax(count(), 2) - 1; --i >= 0; ) { + m_tc.movePosition(EndOfLine); + m_tc.deleteChar(); + m_tc.insertText(" "); + } + m_tc.movePosition(Left, MoveAnchor, 1); + } } else if (key == 'k' || key == Key_Up) { m_tc.movePosition(Up, KeepAnchor, count()); finishMovement(); From 15c89ea26a3a7335a5adcd6177e936f56e57228b Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 13:50:52 +0100 Subject: [PATCH 076/230] handle 'gJ' --- src/plugins/fakevim/handler.cpp | 6 ++++-- tests/auto/fakevim/fakevim.pro | 15 ++++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 7bdd92f3e1d..136c7e8a46f 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -404,9 +404,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) for (int i = qMax(count(), 2) - 1; --i >= 0; ) { m_tc.movePosition(EndOfLine); m_tc.deleteChar(); - m_tc.insertText(" "); + if (!m_gflag) + m_tc.insertText(" "); } - m_tc.movePosition(Left, MoveAnchor, 1); + if (!m_gflag) + m_tc.movePosition(Left, MoveAnchor, 1); } } else if (key == 'k' || key == Key_Up) { m_tc.movePosition(Up, KeepAnchor, count()); diff --git a/tests/auto/fakevim/fakevim.pro b/tests/auto/fakevim/fakevim.pro index 696feeec31c..29936b2568f 100644 --- a/tests/auto/fakevim/fakevim.pro +++ b/tests/auto/fakevim/fakevim.pro @@ -1,9 +1,14 @@ -load(qttest_p4) +QT += testlib + +FAKEVIMSOURCE = /data/qt-creator/src/plugins/fakevim + +INCLUDEPATH += $$FAKEVIMSOURCE SOURCES += \ - main.cpp \ - handler.cpp + main.cpp \ + $$FAKEVIMSOURCE/handler.cpp + +HEADERS += \ + $$FAKEVIMSOURCE/handler.h -HEADER += \ - handler.h From b8b3274fc3a6c0a7d3190d5d8bf10ff2379cf14f Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 16:42:07 +0100 Subject: [PATCH 077/230] small refactoring, make ex command interface public --- src/plugins/fakevim/handler.cpp | 68 +++++++++++++++++++++++++++------ src/plugins/fakevim/handler.h | 10 ++++- 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 136c7e8a46f..d6ff4cd3b19 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -34,8 +34,10 @@ #include "handler.h" #include +#include #include #include +#include #include #include @@ -133,6 +135,7 @@ public: void moveToNextWord(bool simple); void moveToWordBoundary(bool simple, bool forward); void handleFfTt(int key); + void handleCommand(const QString &cmd); FakeVimHandler *q; Mode m_mode; @@ -184,6 +187,8 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) m_lastSearchForward = true; m_register = '"'; m_gflag = false; + m_textedit = 0; + m_plaintextedit = 0; } bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) @@ -555,17 +560,7 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) else m_commandBuffer.chop(1); } else if (key == Key_Return && m_commandCode == ':') { - static QRegExp reGoto("^(\\d+)$"); - if (reGoto.indexIn(m_commandBuffer) != -1) { - int n = reGoto.cap(1).toInt(); - m_tc.setPosition(m_tc.block().document() - ->findBlockByNumber(n - 1).position()); - } else if (m_commandBuffer == "q!" || m_commandBuffer == "q") { - if (m_textedit) - q->quitRequested(m_textedit); - else - q->quitRequested(m_plaintextedit); - } + handleCommand(m_commandBuffer); m_commandBuffer.clear(); m_mode = CommandMode; } else if (key == Key_Return && isSearchCommand()) { @@ -591,6 +586,30 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) updateCommandBuffer(); } +void FakeVimHandler::Private::handleCommand(const QString &cmd) +{ + static QRegExp reGoto("^(\\d+)$"); + if (reGoto.indexIn(cmd) != -1) { + int n = reGoto.cap(1).toInt(); + m_tc.setPosition(m_tc.block().document() + ->findBlockByNumber(n - 1).position()); + } else if (cmd == "q!" || cmd == "q") { + if (m_textedit) + q->quitRequested(m_textedit); + else + q->quitRequested(m_plaintextedit); + } else if (cmd.startsWith("r ")) { + QString fileName = cmd.mid(2); + QFile file(fileName); + file.open(QIODevice::ReadOnly); + QTextStream ts(&file); + if (m_textedit) + m_textedit->setText(ts.readAll()); + else if (m_plaintextedit) + m_plaintextedit->setPlainText(ts.readAll()); + } +} + void FakeVimHandler::Private::search(const QString &needle, bool forward) { //qDebug() << "NEEDLE " << needle << "BACKWARDS" << backwards; @@ -792,3 +811,30 @@ bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev) return d->eventFilter(ob, ev); } +void FakeVimHandler::addWidget(QWidget *widget) +{ + widget->installEventFilter(this); + QFont font = widget->font(); + font.setFamily("Monospace"); + widget->setFont(font); + if (QTextEdit *ed = qobject_cast(widget)) { + ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x'))); + ed->setLineWrapMode(QTextEdit::NoWrap); + } else if (QPlainTextEdit *ed = qobject_cast(widget)) { + ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x'))); + ed->setLineWrapMode(QPlainTextEdit::NoWrap); + } +} + +void FakeVimHandler::removeWidget(QWidget *widget) +{ + widget->removeEventFilter(this); +} + +void FakeVimHandler::handleCommand(QWidget *widget, const QString &cmd) +{ + d->m_textedit = qobject_cast(widget); + d->m_plaintextedit = qobject_cast(widget); + d->handleCommand(cmd); +} + diff --git a/src/plugins/fakevim/handler.h b/src/plugins/fakevim/handler.h index a1e4431adaa..56184aa887f 100644 --- a/src/plugins/fakevim/handler.h +++ b/src/plugins/fakevim/handler.h @@ -52,8 +52,16 @@ public: FakeVimHandler(QObject *parent = 0); ~FakeVimHandler(); + // The same handler can be installed on several widgets + void addWidget(QWidget *widget); + void removeWidget(QWidget *widget); + + // This executes an "ex" style command taking context + // information from \p widget; + void handleCommand(QWidget *widget, const QString &cmd); + signals: - void commandBufferChanged(const QString &); + void commandBufferChanged(const QString &msg); void quitRequested(QObject *); private: From 7e30c9eb5b0f030dae7020b728add8aaeea9d35b Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 19:47:29 +0100 Subject: [PATCH 078/230] partially handle :w and :w! --- src/plugins/fakevim/handler.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index d6ff4cd3b19..0937c34122d 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -282,6 +282,7 @@ void FakeVimHandler::Private::updateCommandBuffer() void FakeVimHandler::Private::showMessage(const QString &msg) { + qDebug() << "MESSAGE" << msg; emit q->commandBufferChanged(msg); } @@ -554,11 +555,13 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_commandBuffer.clear(); m_commandCode = 0; m_mode = CommandMode; + updateCommandBuffer(); } else if (key == Key_Backspace) { if (m_commandBuffer.isEmpty()) m_mode = CommandMode; else m_commandBuffer.chop(1); + updateCommandBuffer(); } else if (key == Key_Return && m_commandCode == ':') { handleCommand(m_commandBuffer); m_commandBuffer.clear(); @@ -570,20 +573,23 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_commandBuffer.clear(); m_commandCode = 0; m_mode = CommandMode; + updateCommandBuffer(); } else if (key == Key_Up && isSearchCommand()) { if (m_searchHistoryIndex > 0) { --m_searchHistoryIndex; m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); } + updateCommandBuffer(); } else if (key == Key_Down && isSearchCommand()) { if (m_searchHistoryIndex < m_searchHistory.size() - 1) { ++m_searchHistoryIndex; m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); } + updateCommandBuffer(); } else { m_commandBuffer += QChar(key); + updateCommandBuffer(); } - updateCommandBuffer(); } void FakeVimHandler::Private::handleCommand(const QString &cmd) @@ -598,15 +604,31 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd) q->quitRequested(m_textedit); else q->quitRequested(m_plaintextedit); + } else if (cmd.startsWith("w ") || cmd.startsWith("w! ")) { + bool forced = cmd.startsWith("w! "); + QString fileName = cmd.mid(forced ? 3 : 2); + QFile file(fileName); + bool exists = file.exists(); + qDebug() << "FORCED: " << forced << exists << fileName; + if (exists && !forced) { + showMessage("E13: File exists (add ! to override)"); + } else { + file.open(QIODevice::ReadWrite); + QTextStream ts(&file); + ts << EDITOR(toPlainText()); + file.close(); + file.open(QIODevice::ReadWrite); + QByteArray ba = file.readAll(); + showMessage(tr("\"%1\" %2 %3L, %4C written") + .arg(fileName).arg(exists ? " " : " [New] ") + .arg(ba.count('\n')).arg(ba.size())); + } } else if (cmd.startsWith("r ")) { QString fileName = cmd.mid(2); QFile file(fileName); file.open(QIODevice::ReadOnly); QTextStream ts(&file); - if (m_textedit) - m_textedit->setText(ts.readAll()); - else if (m_plaintextedit) - m_plaintextedit->setPlainText(ts.readAll()); + EDITOR(setPlainText(ts.readAll())); } } From a0a38305494d1bdc1fa101e9e24d888cf30934b1 Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 21:01:05 +0100 Subject: [PATCH 079/230] show postion in commandline --- src/plugins/fakevim/handler.cpp | 59 +++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 0937c34122d..5ccd4c802bd 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -112,7 +112,7 @@ public: void handleRegisterMode(int key, const QString &text); void handleExMode(int key, const QString &text); void finishMovement(); - void updateCommandBuffer(); + void updateMiniBuffer(); void search(const QString &needle, bool forward); void showMessage(const QString &msg); @@ -128,7 +128,9 @@ public: // all zero-based counting int cursorLineOnScreen() const; int linesOnScreen() const; + int columnsOnScreen() const; int cursorLineInDocument() const; + int cursorColumnInDocument() const; void scrollToLineInDocument(int line); void moveToFirstNonBlankOnLine(); @@ -209,9 +211,8 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) m_tc = EDITOR(textCursor()); if (m_fakeEnd) { - //m_fakeEnd = false; m_tc.movePosition(Right, MoveAnchor, 1); - qDebug() << "Unfake EOL"; + //qDebug() << "Unfake EOL"; } if (key >= Key_A && key <= Key_Z @@ -230,7 +231,7 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) if (m_fakeEnd) { m_tc.movePosition(Left, MoveAnchor, 1); - qDebug() << "Fake EOL"; + //qDebug() << "Fake EOL"; } //qDebug() << "POS: " << m_tc.position() @@ -271,19 +272,29 @@ void FakeVimHandler::Private::finishMovement() m_gflag = false; m_register = '"'; m_tc.clearSelection(); - updateCommandBuffer(); + updateMiniBuffer(); } -void FakeVimHandler::Private::updateCommandBuffer() +void FakeVimHandler::Private::updateMiniBuffer() { - QString msg = QChar(m_commandCode ? m_commandCode : ' ') + m_commandBuffer; + QString msg; + msg = QChar(m_commandCode ? m_commandCode : ' ') + m_commandBuffer; + int l = cursorLineInDocument(); + int w = columnsOnScreen(); + msg += QString(w, ' '); + msg = msg.left(w - 20); + QString pos = tr("%1,%2").arg(l + 1).arg(cursorColumnInDocument() + 1); + msg += tr("%1").arg(pos, -12); + // FIXME: physical "-" logical + msg += tr("%1").arg(l * 100 / (m_tc.document()->blockCount() - 1), 4); + msg += '%'; emit q->commandBufferChanged(msg); } void FakeVimHandler::Private::showMessage(const QString &msg) { - qDebug() << "MESSAGE" << msg; - emit q->commandBufferChanged(msg); + m_commandBuffer = msg; + updateMiniBuffer(); } void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) @@ -335,7 +346,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_commandHistory.append(QString()); m_commandHistoryIndex = m_commandHistory.size() - 1; } - updateCommandBuffer(); + updateMiniBuffer(); } else if (key == '|') { m_tc.movePosition(StartOfLine, KeepAnchor); m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist()) - 1); @@ -555,13 +566,13 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_commandBuffer.clear(); m_commandCode = 0; m_mode = CommandMode; - updateCommandBuffer(); + updateMiniBuffer(); } else if (key == Key_Backspace) { if (m_commandBuffer.isEmpty()) m_mode = CommandMode; else m_commandBuffer.chop(1); - updateCommandBuffer(); + updateMiniBuffer(); } else if (key == Key_Return && m_commandCode == ':') { handleCommand(m_commandBuffer); m_commandBuffer.clear(); @@ -573,22 +584,22 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_commandBuffer.clear(); m_commandCode = 0; m_mode = CommandMode; - updateCommandBuffer(); + updateMiniBuffer(); } else if (key == Key_Up && isSearchCommand()) { if (m_searchHistoryIndex > 0) { --m_searchHistoryIndex; m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); } - updateCommandBuffer(); + updateMiniBuffer(); } else if (key == Key_Down && isSearchCommand()) { if (m_searchHistoryIndex < m_searchHistory.size() - 1) { ++m_searchHistoryIndex; m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); } - updateCommandBuffer(); + updateMiniBuffer(); } else { m_commandBuffer += QChar(key); - updateCommandBuffer(); + updateMiniBuffer(); } } @@ -783,16 +794,25 @@ int FakeVimHandler::Private::cursorLineOnScreen() const int FakeVimHandler::Private::linesOnScreen() const { QRect rect = EDITOR(cursorRect()); - //qDebug() << EDITOR(height()) / rect.height(); return EDITOR(height()) / rect.height(); } +int FakeVimHandler::Private::columnsOnScreen() const +{ + QRect rect = EDITOR(cursorRect()); + return EDITOR(width()) / rect.width(); +} + int FakeVimHandler::Private::cursorLineInDocument() const { - //qDebug() << "CURSOR LINE IN DOCUMENT " << m_tc.block().blockNumber(); return m_tc.block().blockNumber(); } +int FakeVimHandler::Private::cursorColumnInDocument() const +{ + return m_tc.position() - m_tc.block().position(); +} + void FakeVimHandler::Private::scrollToLineInDocument(int line) { // FIXME: works only for QPlainTextEdit @@ -837,7 +857,10 @@ void FakeVimHandler::addWidget(QWidget *widget) { widget->installEventFilter(this); QFont font = widget->font(); + //: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1 + //font.setFamily("Misc"); font.setFamily("Monospace"); + font.setStretch(QFont::SemiCondensed); widget->setFont(font); if (QTextEdit *ed = qobject_cast(widget)) { ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x'))); From f932c51a04fd9d414ca1bf1a56c03c267431b850 Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 21:28:22 +0100 Subject: [PATCH 080/230] implement 'G' --- src/plugins/fakevim/handler.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 5ccd4c802bd..80fdc8fa4e6 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -95,6 +95,9 @@ enum SubSubMode FtSubSubMode, // used for f, F, t, T }; +static const QString ConfigStartOfLine = "startofline"; +static const QString ConfigOn = "on"; + class FakeVimHandler::Private { public: @@ -131,6 +134,7 @@ public: int columnsOnScreen() const; int cursorLineInDocument() const; int cursorColumnInDocument() const; + int linesInDocument() const { return m_tc.document()->blockCount(); } void scrollToLineInDocument(int line); void moveToFirstNonBlankOnLine(); @@ -176,6 +180,11 @@ public: // History for ':' QStringList m_commandHistory; int m_commandHistoryIndex; + + // + // vi style configuration + // + QHash m_config; }; FakeVimHandler::Private::Private(FakeVimHandler *parent) @@ -191,6 +200,9 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) m_gflag = false; m_textedit = 0; m_plaintextedit = 0; + + // vi style configuration + m_config[ConfigStartOfLine] = ConfigOn; } bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) @@ -399,6 +411,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_subsubdata = key; } else if (key == 'g') { m_gflag = true; + } else if (key == 'G') { + int n = m_mvcount.isEmpty() ? linesInDocument() : count(); + m_tc.setPosition(m_tc.document()->findBlockByNumber(n - 1).position()); + if (m_config.contains(ConfigStartOfLine)) + moveToFirstNonBlankOnLine(); + finishMovement(); } else if (key == 'h' || key == Key_Left) { int n = qMin(count(), leftDist()); if (m_fakeEnd && m_tc.block().length() > 1) From bbe5332fce86ab0f39a825911f639483d6438ba5 Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 21:51:06 +0100 Subject: [PATCH 081/230] implement 'a' --- src/plugins/fakevim/handler.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 80fdc8fa4e6..487ac32f293 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -374,8 +374,13 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == '$' || key == Key_End) { m_tc.movePosition(EndOfLine, KeepAnchor); finishMovement(); + } else if (key == 'a') { + m_lastInsertion.clear(); + m_tc.movePosition(Right, MoveAnchor, 1); + m_mode = InsertMode; } else if (key == 'A') { m_tc.movePosition(EndOfLine, MoveAnchor); + m_lastInsertion.clear(); m_mode = InsertMode; } else if (key == 'b') { moveToWordBoundary(false, false); @@ -435,6 +440,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(Down, KeepAnchor, count()); finishMovement(); } else if (key == 'J') { + m_tc.beginEditBlock(); if (m_submode == NoSubMode) { for (int i = qMax(count(), 2) - 1; --i >= 0; ) { m_tc.movePosition(EndOfLine); @@ -445,6 +451,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) if (!m_gflag) m_tc.movePosition(Left, MoveAnchor, 1); } + m_tc.endEditBlock(); } else if (key == 'k' || key == Key_Up) { m_tc.movePosition(Up, KeepAnchor, count()); finishMovement(); From 6bfe250e2cefbfbc4f30c7e718184c49bcea5591 Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 22:22:16 +0100 Subject: [PATCH 082/230] improve undo/redo block behaviour --- src/plugins/fakevim/handler.cpp | 21 ++++++++++++++++----- src/plugins/fakevim/handler.h | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 487ac32f293..255892e3ed3 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -375,13 +375,15 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(EndOfLine, KeepAnchor); finishMovement(); } else if (key == 'a') { - m_lastInsertion.clear(); - m_tc.movePosition(Right, MoveAnchor, 1); m_mode = InsertMode; + m_lastInsertion.clear(); + m_tc.beginEditBlock(); + m_tc.movePosition(Right, MoveAnchor, 1); } else if (key == 'A') { + m_mode = InsertMode; + m_tc.beginEditBlock(); m_tc.movePosition(EndOfLine, MoveAnchor); m_lastInsertion.clear(); - m_mode = InsertMode; } else if (key == 'b') { moveToWordBoundary(false, false); finishMovement(); @@ -390,8 +392,10 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key == 'c') { m_submode = ChangeSubMode; + m_tc.beginEditBlock(); } else if (key == 'C') { m_submode = ChangeSubMode; + m_tc.beginEditBlock(); m_tc.movePosition(EndOfLine, KeepAnchor); finishMovement(); } else if (key == 'd') { @@ -434,8 +438,9 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) moveToFirstNonBlankOnLine(); finishMovement(); } else if (key == 'i') { - m_lastInsertion.clear(); m_mode = InsertMode; + m_tc.beginEditBlock(); + m_lastInsertion.clear(); } else if (key == 'j' || key == Key_Down) { m_tc.movePosition(Down, KeepAnchor, count()); finishMovement(); @@ -488,6 +493,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } } else if (key == control('r')) { EDITOR(redo()); + } else if (key == 's') { + m_submode = ChangeSubMode; + m_tc.beginEditBlock(); + m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); + finishMovement(); } else if (key == 't' || key == 'T') { m_subsubmode = FtSubSubMode; m_subsubdata = key; @@ -542,10 +552,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) { if (key == Key_Escape) { - m_mode = CommandMode; for (int i = 1; i < count(); ++i) m_tc.insertText(m_lastInsertion); m_tc.movePosition(Left, MoveAnchor, qMin(1, leftDist())); + m_mode = CommandMode; + m_tc.endEditBlock(); } else if (key == Key_Left) { m_tc.movePosition(Left, MoveAnchor, 1); m_lastInsertion.clear(); diff --git a/src/plugins/fakevim/handler.h b/src/plugins/fakevim/handler.h index 56184aa887f..1ebf9adb8e4 100644 --- a/src/plugins/fakevim/handler.h +++ b/src/plugins/fakevim/handler.h @@ -62,7 +62,7 @@ public: signals: void commandBufferChanged(const QString &msg); - void quitRequested(QObject *); + void quitRequested(QWidget *); private: bool eventFilter(QObject *ob, QEvent *ev); From fd76b100bdfd8be3d8df66f014cdeea3d3619831 Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 22:41:47 +0100 Subject: [PATCH 083/230] improve handling of tab searching --- src/plugins/fakevim/handler.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 255892e3ed3..3f2a2849efc 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -290,7 +290,16 @@ void FakeVimHandler::Private::finishMovement() void FakeVimHandler::Private::updateMiniBuffer() { QString msg; - msg = QChar(m_commandCode ? m_commandCode : ' ') + m_commandBuffer; + msg = QChar(m_commandCode ? m_commandCode : ' '); + for (int i = 0; i != m_commandBuffer.size(); ++i) { + QChar c = m_commandBuffer.at(i); + if (c.unicode() < 64) { + msg += '^'; + msg += QChar(c.unicode() + 64); + } else { + msg += c; + } + } int l = cursorLineInDocument(); int w = columnsOnScreen(); msg += QString(w, ' '); @@ -633,6 +642,9 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); } updateMiniBuffer(); + } else if (key == Key_Tab) { + m_commandBuffer += QChar(9); + updateMiniBuffer(); } else { m_commandBuffer += QChar(key); updateMiniBuffer(); From fd79edf7cf4b5d96a9d3e366a6fec100a8648d3b Mon Sep 17 00:00:00 2001 From: hjk Date: Sat, 27 Dec 2008 22:50:58 +0100 Subject: [PATCH 084/230] code cosmetics --- src/plugins/fakevim/handler.cpp | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 3f2a2849efc..9d01a2242fa 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -181,15 +181,14 @@ public: QStringList m_commandHistory; int m_commandHistoryIndex; - // // vi style configuration - // QHash m_config; }; FakeVimHandler::Private::Private(FakeVimHandler *parent) { q = parent; + m_mode = CommandMode; m_submode = NoSubMode; m_subsubmode = NoSubSubMode; @@ -201,7 +200,6 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) m_textedit = 0; m_plaintextedit = 0; - // vi style configuration m_config[ConfigStartOfLine] = ConfigOn; } @@ -212,7 +210,6 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) if (key == Key_Shift || key == Key_Alt || key == Key_Control || key == Key_Alt || key == Key_AltGr || key == Key_Meta) return false; - //qDebug() << "KEY: " << key << Qt::ShiftModifier; // Fake "End of line" m_textedit = qobject_cast(ob); @@ -222,10 +219,8 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) m_tc = EDITOR(textCursor()); - if (m_fakeEnd) { + if (m_fakeEnd) m_tc.movePosition(Right, MoveAnchor, 1); - //qDebug() << "Unfake EOL"; - } if (key >= Key_A && key <= Key_Z && (keyEvent->modifiers() & Qt::ShiftModifier) == 0) @@ -235,20 +230,10 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) handleKey(key, keyEvent->text()); // We fake vi-style end-of-line behaviour - m_fakeEnd = atEol() && m_mode == CommandMode; + m_fakeEnd = (atEol() && m_mode == CommandMode); - //qDebug() << "POS: " << m_tc.position() - // << " BLOCK LEN: " << m_tc.block().length() - // << " LEFT: " << leftDist() << " RIGHT: " << rightDist(); - - if (m_fakeEnd) { + if (m_fakeEnd) m_tc.movePosition(Left, MoveAnchor, 1); - //qDebug() << "Fake EOL"; - } - - //qDebug() << "POS: " << m_tc.position() - // << " BLOCK LEN: " << m_tc.block().length() - // << " LEFT: " << leftDist() << " RIGHT: " << rightDist(); EDITOR(setTextCursor(m_tc)); EDITOR(ensureCursorVisible()); @@ -322,7 +307,6 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) { Q_UNUSED(text) - //qDebug() << "-> MODE: " << m_mode << " KEY: " << key; if (m_submode == RegisterSubMode) { m_register = key; m_submode = NoSubMode; @@ -473,14 +457,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); finishMovement(); } else if (key == 'L') { - int heigth = EDITOR(height()); - m_tc = EDITOR(cursorForPosition(QPoint(0, heigth))); + m_tc = EDITOR(cursorForPosition(QPoint(0, EDITOR(height())))); m_tc.movePosition(Up, KeepAnchor, qMax(count(), 1)); moveToFirstNonBlankOnLine(); finishMovement(); } else if (key == 'M') { - int heigth = EDITOR(height()); - m_tc = EDITOR(cursorForPosition(QPoint(0, heigth / 2))); + m_tc = EDITOR(cursorForPosition(QPoint(0, EDITOR(height()) / 2))); moveToFirstNonBlankOnLine(); finishMovement(); } else if (key == 'n') { @@ -668,7 +650,6 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd) QString fileName = cmd.mid(forced ? 3 : 2); QFile file(fileName); bool exists = file.exists(); - qDebug() << "FORCED: " << forced << exists << fileName; if (exists && !forced) { showMessage("E13: File exists (add ! to override)"); } else { From 87aa0759b2b41a629420299f2a7da4fa2e7170d6 Mon Sep 17 00:00:00 2001 From: hjk Date: Sun, 28 Dec 2008 00:32:07 +0100 Subject: [PATCH 085/230] introduce history for ex commands --- src/plugins/fakevim/handler.cpp | 45 +++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 9d01a2242fa..f07cd6744fe 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -278,7 +278,7 @@ void FakeVimHandler::Private::updateMiniBuffer() msg = QChar(m_commandCode ? m_commandCode : ' '); for (int i = 0; i != m_commandBuffer.size(); ++i) { QChar c = m_commandBuffer.at(i); - if (c.unicode() < 64) { + if (c.unicode() < 32) { msg += '^'; msg += QChar(c.unicode() + 64); } else { @@ -601,27 +601,44 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_commandBuffer.chop(1); updateMiniBuffer(); } else if (key == Key_Return && m_commandCode == ':') { - handleCommand(m_commandBuffer); - m_commandBuffer.clear(); - m_mode = CommandMode; - } else if (key == Key_Return && isSearchCommand()) { - m_lastSearchForward = (m_commandCode == '/'); - m_searchHistory.append(m_commandBuffer); - search(lastSearchString(), m_lastSearchForward); - m_commandBuffer.clear(); - m_commandCode = 0; + if (!m_commandBuffer.isEmpty()) { + m_commandHistory.takeLast(); + m_commandHistory.append(m_commandBuffer); + handleCommand(m_commandBuffer); + m_commandBuffer.clear(); + m_commandCode = 0; + } m_mode = CommandMode; updateMiniBuffer(); - } else if (key == Key_Up && isSearchCommand()) { - if (m_searchHistoryIndex > 0) { + } else if (key == Key_Return && isSearchCommand()) { + if (!m_commandBuffer.isEmpty()) { + m_searchHistory.takeLast(); + m_searchHistory.append(m_commandBuffer); + m_lastSearchForward = (m_commandCode == '/'); + search(lastSearchString(), m_lastSearchForward); + m_commandBuffer.clear(); + m_commandCode = 0; + } + m_mode = CommandMode; + updateMiniBuffer(); + } else if (key == Key_Up) { + if (isSearchCommand() && m_searchHistoryIndex > 0) { --m_searchHistoryIndex; m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); + } else if (m_commandCode == ':' && m_commandHistoryIndex > 0) { + --m_commandHistoryIndex; + m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex); } updateMiniBuffer(); - } else if (key == Key_Down && isSearchCommand()) { - if (m_searchHistoryIndex < m_searchHistory.size() - 1) { + } else if (key == Key_Down) { + if (isSearchCommand() + && m_searchHistoryIndex < m_searchHistory.size() - 1) { ++m_searchHistoryIndex; m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); + } else if (m_commandCode == ':' + && m_commandHistoryIndex < m_commandHistory.size() - 1) { + ++m_commandHistoryIndex; + m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex); } updateMiniBuffer(); } else if (key == Key_Tab) { From 8beff13ef675e94cf2619ff0a12c5d6013940931 Mon Sep 17 00:00:00 2001 From: hjk Date: Sun, 28 Dec 2008 01:02:54 +0100 Subject: [PATCH 086/230] add notion of currentFileName to support ':w' without file name --- src/plugins/fakevim/handler.cpp | 69 +++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index f07cd6744fe..efa11e87692 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -168,6 +168,8 @@ public: int m_gflag; // whether current command started with 'g' QString m_commandBuffer; + QString m_currentFileName; + QString m_currentMessage; bool m_lastSearchForward; QString m_lastInsertion; @@ -274,16 +276,23 @@ void FakeVimHandler::Private::finishMovement() void FakeVimHandler::Private::updateMiniBuffer() { + if (m_tc.isNull()) + return; QString msg; - msg = QChar(m_commandCode ? m_commandCode : ' '); - for (int i = 0; i != m_commandBuffer.size(); ++i) { - QChar c = m_commandBuffer.at(i); - if (c.unicode() < 32) { - msg += '^'; - msg += QChar(c.unicode() + 64); - } else { - msg += c; + if (m_currentMessage.isEmpty()) { + msg = QChar(m_commandCode ? m_commandCode : ' '); + for (int i = 0; i != m_commandBuffer.size(); ++i) { + QChar c = m_commandBuffer.at(i); + if (c.unicode() < 32) { + msg += '^'; + msg += QChar(c.unicode() + 64); + } else { + msg += c; + } } + } else { + msg = m_currentMessage; + m_currentMessage.clear(); } int l = cursorLineInDocument(); int w = columnsOnScreen(); @@ -299,7 +308,8 @@ void FakeVimHandler::Private::updateMiniBuffer() void FakeVimHandler::Private::showMessage(const QString &msg) { - m_commandBuffer = msg; + //qDebug() << "MSG: " << msg; + m_currentMessage = msg; updateMiniBuffer(); } @@ -609,7 +619,6 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_commandCode = 0; } m_mode = CommandMode; - updateMiniBuffer(); } else if (key == Key_Return && isSearchCommand()) { if (!m_commandBuffer.isEmpty()) { m_searchHistory.takeLast(); @@ -621,26 +630,30 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) } m_mode = CommandMode; updateMiniBuffer(); - } else if (key == Key_Up) { - if (isSearchCommand() && m_searchHistoryIndex > 0) { + } else if (key == Key_Up && isSearchCommand()) { + if (m_searchHistoryIndex > 0) { --m_searchHistoryIndex; m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); - } else if (m_commandCode == ':' && m_commandHistoryIndex > 0) { + updateMiniBuffer(); + } + } else if (key == Key_Up && m_commandCode == ':') { + if (m_commandHistoryIndex > 0) { --m_commandHistoryIndex; m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex); + updateMiniBuffer(); } - updateMiniBuffer(); - } else if (key == Key_Down) { - if (isSearchCommand() - && m_searchHistoryIndex < m_searchHistory.size() - 1) { + } else if (key == Key_Down && isSearchCommand()) { + if (m_searchHistoryIndex < m_searchHistory.size() - 1) { ++m_searchHistoryIndex; m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); - } else if (m_commandCode == ':' - && m_commandHistoryIndex < m_commandHistory.size() - 1) { + updateMiniBuffer(); + } + } else if (key == Key_Down && m_commandCode == ':') { + if (m_commandHistoryIndex < m_commandHistory.size() - 1) { ++m_commandHistoryIndex; m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex); + updateMiniBuffer(); } - updateMiniBuffer(); } else if (key == Key_Tab) { m_commandBuffer += QChar(9); updateMiniBuffer(); @@ -653,18 +666,23 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) void FakeVimHandler::Private::handleCommand(const QString &cmd) { static QRegExp reGoto("^(\\d+)$"); + static QRegExp reWrite("^w!?( (.*))?$"); if (reGoto.indexIn(cmd) != -1) { int n = reGoto.cap(1).toInt(); m_tc.setPosition(m_tc.block().document() ->findBlockByNumber(n - 1).position()); + showMessage(QString()); } else if (cmd == "q!" || cmd == "q") { if (m_textedit) q->quitRequested(m_textedit); else q->quitRequested(m_plaintextedit); - } else if (cmd.startsWith("w ") || cmd.startsWith("w! ")) { - bool forced = cmd.startsWith("w! "); - QString fileName = cmd.mid(forced ? 3 : 2); + showMessage(QString()); + } else if (reWrite.indexIn(cmd) != -1) { + bool forced = cmd.startsWith("w!"); + QString fileName = reWrite.cap(2); + if (fileName.isEmpty()) + fileName = m_currentFileName; QFile file(fileName); bool exists = file.exists(); if (exists && !forced) { @@ -681,11 +699,12 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd) .arg(ba.count('\n')).arg(ba.size())); } } else if (cmd.startsWith("r ")) { - QString fileName = cmd.mid(2); - QFile file(fileName); + m_currentFileName = cmd.mid(2); + QFile file(m_currentFileName); file.open(QIODevice::ReadOnly); QTextStream ts(&file); EDITOR(setPlainText(ts.readAll())); + showMessage(QString()); } } From a705a8a322133cd7d00827751bdf3926ac131436 Mon Sep 17 00:00:00 2001 From: hjk Date: Sun, 28 Dec 2008 02:15:26 +0100 Subject: [PATCH 087/230] improve range parsing for ex commands --- src/plugins/fakevim/handler.cpp | 78 ++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index efa11e87692..9807f867132 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -134,7 +134,7 @@ public: int columnsOnScreen() const; int cursorLineInDocument() const; int cursorColumnInDocument() const; - int linesInDocument() const { return m_tc.document()->blockCount(); } + int linesInDocument() const; void scrollToLineInDocument(int line); void moveToFirstNonBlankOnLine(); @@ -143,6 +143,9 @@ public: void handleFfTt(int key); void handleCommand(const QString &cmd); + // helper function for handleCommand. return 1 based line index. + int readLineCode(QString &cmd); + FakeVimHandler *q; Mode m_mode; SubMode m_submode; @@ -663,14 +666,70 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) } } -void FakeVimHandler::Private::handleCommand(const QString &cmd) +// 1 based. +int FakeVimHandler::Private::readLineCode(QString &cmd) { - static QRegExp reGoto("^(\\d+)$"); + //qDebug() << "CMD: " << cmd; + if (cmd.isEmpty()) + return -1; + QChar c = cmd.at(0); + cmd = cmd.mid(1); + if (c == '.') + return cursorLineInDocument() + 1; + if (c == '$') + return linesInDocument(); + if (c == '-') { + int n = readLineCode(cmd); + return cursorLineInDocument() + 1 - (n == -1 ? 1 : n); + } + if (c == '+') { + int n = readLineCode(cmd); + return cursorLineInDocument() + 1 + (n == -1 ? 1 : n); + } + if (c.isDigit()) { + int n = c.unicode() - '0'; + while (!cmd.isEmpty()) { + c = cmd.at(0); + if (!c.isDigit()) + break; + cmd = cmd.mid(1); + n = n * 10 + (c.unicode() - '0'); + } + //qDebug() << "N: " << n; + return n; + } + // not parsed + cmd = c + cmd; + return -1; +} + +void FakeVimHandler::Private::handleCommand(const QString &cmd0) +{ + QString cmd = cmd0; + if (cmd.startsWith("%")) + cmd = "1,$" + cmd.mid(1); + + int beginLine = 0; + int endLine = linesInDocument(); + + int line = readLineCode(cmd); + if (line != -1) + beginLine = line; + + if (cmd.startsWith(',')) { + cmd = cmd.mid(1); + line = readLineCode(cmd); + if (line != -1) + endLine = line; + } + + //qDebug() << "RANGE: " << beginLine << endLine << cmd << cmd0; + static QRegExp reWrite("^w!?( (.*))?$"); - if (reGoto.indexIn(cmd) != -1) { - int n = reGoto.cap(1).toInt(); + + if (cmd.isEmpty()) { m_tc.setPosition(m_tc.block().document() - ->findBlockByNumber(n - 1).position()); + ->findBlockByNumber(beginLine - 1).position()); showMessage(QString()); } else if (cmd == "q!" || cmd == "q") { if (m_textedit) @@ -705,6 +764,8 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd) QTextStream ts(&file); EDITOR(setPlainText(ts.readAll())); showMessage(QString()); + } else { + showMessage("E492: Not an editor command: " + cmd0); } } @@ -878,6 +939,11 @@ int FakeVimHandler::Private::cursorColumnInDocument() const return m_tc.position() - m_tc.block().position(); } +int FakeVimHandler::Private::linesInDocument() const +{ + return m_tc.isNull() ? 0 : m_tc.document()->blockCount(); +} + void FakeVimHandler::Private::scrollToLineInDocument(int line) { // FIXME: works only for QPlainTextEdit From 50cf2a7a0644c7b2dbc7cb7a0c3bee83ebcaf7f8 Mon Sep 17 00:00:00 2001 From: hjk Date: Sun, 28 Dec 2008 02:32:44 +0100 Subject: [PATCH 088/230] basic implementation of 'o' --- src/plugins/fakevim/handler.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 9807f867132..22f78b44bbf 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -68,6 +68,7 @@ using namespace FakeVim::Internal; /////////////////////////////////////////////////////////////////////// #define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s) +#define THE_EDITOR (m_textedit ? (QWidget*)m_textedit : (QWidget*)m_plaintextedit) const int ParagraphSeparator = 0x00002029; @@ -482,6 +483,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) search(lastSearchString(), m_lastSearchForward); } else if (key == 'N') { search(lastSearchString(), !m_lastSearchForward); + } else if (key == 'o') { + m_mode = InsertMode; + m_lastInsertion.clear(); + //m_tc.beginEditBlock(); // FIXME: unusable due to drawing errors + m_tc.movePosition(EndOfLine, MoveAnchor); + m_tc.insertText("\n"); } else if (key == 'p') { QString text = m_registers[m_register]; int n = text.count(QChar(ParagraphSeparator)); @@ -732,10 +739,7 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) ->findBlockByNumber(beginLine - 1).position()); showMessage(QString()); } else if (cmd == "q!" || cmd == "q") { - if (m_textedit) - q->quitRequested(m_textedit); - else - q->quitRequested(m_plaintextedit); + q->quitRequested(THE_EDITOR); showMessage(QString()); } else if (reWrite.indexIn(cmd) != -1) { bool forced = cmd.startsWith("w!"); From 0dc5a124bf4044b52cd87b8695083caabbb7701b Mon Sep 17 00:00:00 2001 From: hjk Date: Sun, 28 Dec 2008 02:42:10 +0100 Subject: [PATCH 089/230] basic implementation for 'O' --- src/plugins/fakevim/handler.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 22f78b44bbf..b6e9bc82ce9 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -489,6 +489,13 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) //m_tc.beginEditBlock(); // FIXME: unusable due to drawing errors m_tc.movePosition(EndOfLine, MoveAnchor); m_tc.insertText("\n"); + } else if (key == 'O') { + m_mode = InsertMode; + m_lastInsertion.clear(); + //m_tc.beginEditBlock(); // FIXME: unusable due to drawing errors + m_tc.movePosition(StartOfLine, MoveAnchor); + m_tc.movePosition(Left, MoveAnchor, 1); + m_tc.insertText("\n"); } else if (key == 'p') { QString text = m_registers[m_register]; int n = text.count(QChar(ParagraphSeparator)); From c480442a8261ad83feb5973b05e47e1a81f92275 Mon Sep 17 00:00:00 2001 From: hjk Date: Sun, 28 Dec 2008 02:44:43 +0100 Subject: [PATCH 090/230] basic implementation of 'I' --- src/plugins/fakevim/handler.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index b6e9bc82ce9..77d691ca8b1 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -448,6 +448,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_mode = InsertMode; m_tc.beginEditBlock(); m_lastInsertion.clear(); + } else if (key == 'I') { + m_mode = InsertMode; + moveToFirstNonBlankOnLine(); + m_tc.clearSelection(); + m_tc.beginEditBlock(); + m_lastInsertion.clear(); } else if (key == 'j' || key == Key_Down) { m_tc.movePosition(Down, KeepAnchor, count()); finishMovement(); From 6d03617cce78f1b5371da1ccc9ba9397a677aaad Mon Sep 17 00:00:00 2001 From: hjk Date: Sun, 28 Dec 2008 02:49:14 +0100 Subject: [PATCH 091/230] implement 'I' and 'gI' --- src/plugins/fakevim/handler.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 77d691ca8b1..a50105fdf2d 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -350,7 +350,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key >= '0' && key <= '9') { if (key == '0' && m_mvcount.isEmpty()) { - m_tc.movePosition(StartOfLine, KeepAnchor); + moveToFirstNonBlankOnLine(); finishMovement(); } else { m_mvcount.append(QChar(key)); @@ -450,7 +450,10 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_lastInsertion.clear(); } else if (key == 'I') { m_mode = InsertMode; - moveToFirstNonBlankOnLine(); + if (m_gflag) + m_tc.movePosition(StartOfLine, KeepAnchor); + else + moveToFirstNonBlankOnLine(); m_tc.clearSelection(); m_tc.beginEditBlock(); m_lastInsertion.clear(); From 2377567f2689340a21f71f06abb403de0c33a7e8 Mon Sep 17 00:00:00 2001 From: hjk Date: Sun, 28 Dec 2008 03:07:52 +0100 Subject: [PATCH 092/230] basic mark handling (setting, jumping to) --- src/plugins/fakevim/handler.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index a50105fdf2d..fd8734f2114 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -93,7 +93,10 @@ enum SubMode enum SubSubMode { NoSubSubMode, - FtSubSubMode, // used for f, F, t, T + FtSubSubMode, // used for f, F, t, T + MarkSubSubMode, // used for m + BackTickSubSubMode, // used for ` + TickSubSubMode // used for ' }; static const QString ConfigStartOfLine = "startofline"; @@ -187,6 +190,9 @@ public: QStringList m_commandHistory; int m_commandHistoryIndex; + // marks as lines + QHash m_marks; + // vi style configuration QHash m_config; }; @@ -348,6 +354,20 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) handleFfTt(key); m_subsubmode = NoSubSubMode; finishMovement(); + } else if (m_subsubmode == MarkSubSubMode) { + m_marks[key] = m_tc.position(); + m_subsubmode = NoSubSubMode; + } else if (m_subsubmode == BackTickSubSubMode + || m_subsubmode == TickSubSubMode) { + if (m_marks.contains(key)) { + m_tc.setPosition(m_marks[key]); + if (m_subsubmode == TickSubSubMode) + moveToFirstNonBlankOnLine(); + finishMovement(); + } else { + showMessage(tr("E20: Mark '%1' not set").arg(text)); + } + m_subsubmode = NoSubSubMode; } else if (key >= '0' && key <= '9') { if (key == '0' && m_mvcount.isEmpty()) { moveToFirstNonBlankOnLine(); @@ -366,6 +386,10 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_commandHistoryIndex = m_commandHistory.size() - 1; } updateMiniBuffer(); + } else if (key == '`') { + m_subsubmode = BackTickSubSubMode; + } else if (key == '\'') { + m_subsubmode = TickSubSubMode; } else if (key == '|') { m_tc.movePosition(StartOfLine, KeepAnchor); m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist()) - 1); @@ -484,6 +508,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(Up, KeepAnchor, qMax(count(), 1)); moveToFirstNonBlankOnLine(); finishMovement(); + } else if (key == 'm') { + m_subsubmode = MarkSubSubMode; } else if (key == 'M') { m_tc = EDITOR(cursorForPosition(QPoint(0, EDITOR(height()) / 2))); moveToFirstNonBlankOnLine(); @@ -657,6 +683,8 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_mode = CommandMode; updateMiniBuffer(); } else if (key == Key_Up && isSearchCommand()) { + // FIXME: This and the three cases below are wrong as vim + // takes only matching entires in the history into account. if (m_searchHistoryIndex > 0) { --m_searchHistoryIndex; m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); From 702e078ace5b8e091da1e02ea240c42222b2c002 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 30 Dec 2008 11:16:45 +0100 Subject: [PATCH 093/230] oops! update errorCount after the semantic pass. --- tests/auto/cplusplus/semantic/tst_semantic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index ccc388e279a..41d7a71d144 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -85,8 +85,8 @@ public: diag.errorCount = 0; // reset the error count. TranslationUnit *unit = parse(source, TranslationUnit::ParseTranlationUnit); QSharedPointer doc(new Document(unit)); - doc->errorCount = diag.errorCount; doc->check(); + doc->errorCount = diag.errorCount; return doc; } From f6f0c81021f16c31f014ab5d43bc2dab2702ce3e Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 30 Dec 2008 11:35:30 +0100 Subject: [PATCH 094/230] Improved CppCodeCompletion::completeScope(). Added simple support for typedefs. --- src/plugins/cpptools/cppcodecompletion.cpp | 33 +++++++++++++++------- src/plugins/cpptools/cppcodecompletion.h | 3 +- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 075a55b96e9..947bea8f6f7 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -515,7 +515,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) } if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) && completeMember(exprTy, resolvedTypes, context)) { return m_startPosition; - } else if (m_completionOperator == T_COLON_COLON && completeScope(exprTy, resolvedTypes, context)) { + } else if (m_completionOperator == T_COLON_COLON && completeScope(resolvedTypes, context)) { return m_startPosition; } else if (m_completionOperator == T_SIGNAL && completeSignal(exprTy, resolvedTypes, context)) { return m_startPosition; @@ -682,32 +682,45 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, return false; } -bool CppCodeCompletion::completeScope(FullySpecifiedType exprTy, - const QList &resolvedTypes, +bool CppCodeCompletion::completeScope(const QList &results, const LookupContext &context) { + if (results.isEmpty()) + return false; // nothing to do. + // Search for a class or a namespace. - foreach (TypeOfExpression::Result p, resolvedTypes) { - if (p.first->isClass() || p.first->isNamespace()) { - exprTy = p.first; + TypeOfExpression::Result result(FullySpecifiedType(), 0); + foreach (result, results) { + FullySpecifiedType ty = result.first; + + if (ty->isClass() || ty->isNamespace()) break; - } } - if (exprTy->asNamespace()) { + FullySpecifiedType exprTy = result.first; + if (! exprTy) { + return false; + } else if (exprTy->asNamespace()) { QList candidates; - foreach (TypeOfExpression::Result p, resolvedTypes) { + foreach (TypeOfExpression::Result p, results) { if (Namespace *ns = p.first->asNamespace()) candidates.append(ns); } completeNamespace(candidates, context); } else if (exprTy->isClass()) { QList candidates; - foreach (TypeOfExpression::Result p, resolvedTypes) { + foreach (TypeOfExpression::Result p, results) { if (Class *k = p.first->asClass()) candidates.append(k); } completeClass(candidates, context); + } else if (Symbol *symbol = result.second) { + if (symbol->isTypedef()) { + SymbolsForDotAccess symbolsForDotAccess; + const QList candidates = symbolsForDotAccess(result, + context); + completeClass(candidates, context); + } } return ! m_completions.isEmpty(); diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h index baf278e71d0..faaaec3570b 100644 --- a/src/plugins/cpptools/cppcodecompletion.h +++ b/src/plugins/cpptools/cppcodecompletion.h @@ -100,8 +100,7 @@ private: const QList &, const CPlusPlus::LookupContext &context); - bool completeScope(CPlusPlus::FullySpecifiedType exprTy, - const QList &, + bool completeScope(const QList &, const CPlusPlus::LookupContext &context); void completeNamespace(const QList &candidates, From 12ee869eda978a9e40127262c078dcc9ae0cc748 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 30 Dec 2008 11:45:41 +0100 Subject: [PATCH 095/230] Simple typedef support for T_ARROW member access. --- src/plugins/cpptools/cppcodecompletion.cpp | 23 +++++++++++----------- src/plugins/cpptools/cppcodecompletion.h | 3 +-- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 947bea8f6f7..ab389d0a3b3 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -513,7 +513,7 @@ int CppCodeCompletion::startCompletion(TextEditor::ITextEditable *editor) if (m_completionOperator == T_LPAREN && completeFunction(exprTy, resolvedTypes, context)) { return m_startPosition; } if ((m_completionOperator == T_DOT || m_completionOperator == T_ARROW) && - completeMember(exprTy, resolvedTypes, context)) { + completeMember(resolvedTypes, context)) { return m_startPosition; } else if (m_completionOperator == T_COLON_COLON && completeScope(resolvedTypes, context)) { return m_startPosition; @@ -575,8 +575,7 @@ bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy, return ! m_completions.isEmpty(); } -bool CppCodeCompletion::completeMember(FullySpecifiedType, - const QList &results, +bool CppCodeCompletion::completeMember(const QList &results, const LookupContext &context) { if (results.isEmpty()) @@ -593,10 +592,10 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, if (NamedType *namedTy = ty->asNamedType()) { ResolveExpression resolveExpression(context); + SymbolsForDotAccess symbolsForDotAccess; - Name *className = namedTy->name(); - const QList candidates = - context.resolveClass(className, context.visibleScopes(p)); + const QList candidates = symbolsForDotAccess(namedTy, p, + context); foreach (Symbol *classObject, candidates) { const QList overloads = @@ -617,8 +616,7 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, if (PointerType *ptrTy = ty->asPointerType()) { if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { const QList classes = - context.resolveClass(namedTy->name(), - context.visibleScopes(p)); + symbolsForDotAccess(namedTy, p, context); foreach (Symbol *c, classes) { if (! classObjectCandidates.contains(c)) @@ -630,9 +628,10 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, } } else if (PointerType *ptrTy = ty->asPointerType()) { if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { - const QList classes = - context.resolveClass(namedTy->name(), - context.visibleScopes(p)); + SymbolsForDotAccess symbolsForDotAccess; + + const QList classes = symbolsForDotAccess(namedTy, p, + context); foreach (Symbol *c, classes) { if (! classObjectCandidates.contains(c)) @@ -652,7 +651,7 @@ bool CppCodeCompletion::completeMember(FullySpecifiedType, int length = m_editor->position() - m_startPosition + 1; m_editor->setCurPos(m_startPosition - 1); m_editor->replace(length, QLatin1String("->")); - m_startPosition++; + ++m_startPosition; namedTy = ptrTy->elementType()->asNamedType(); } else { namedTy = ty->asNamedType(); diff --git a/src/plugins/cpptools/cppcodecompletion.h b/src/plugins/cpptools/cppcodecompletion.h index faaaec3570b..5720adbbc51 100644 --- a/src/plugins/cpptools/cppcodecompletion.h +++ b/src/plugins/cpptools/cppcodecompletion.h @@ -96,8 +96,7 @@ private: const QList &, const CPlusPlus::LookupContext &context); - bool completeMember(CPlusPlus::FullySpecifiedType exprTy, - const QList &, + bool completeMember(const QList &, const CPlusPlus::LookupContext &context); bool completeScope(const QList &, From 7c3d1a0158a845005f509fb58f5daf3cffdf3563 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 30 Dec 2008 11:54:42 +0100 Subject: [PATCH 096/230] Improved typedef support. --- src/libs/cplusplus/ResolveExpression.cpp | 27 ++++++++++++++---------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index a4d1de3afad..8653d7820f6 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -427,6 +427,7 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast) bool ResolveExpression::visit(QualifiedNameAST *ast) { + SymbolsForDotAccess symbolsForDotAcces; Scope dummy; Name *name = sem.check(ast, &dummy); @@ -435,7 +436,8 @@ bool ResolveExpression::visit(QualifiedNameAST *ast) if (symbol->isTypedef()) { if (NamedType *namedTy = symbol->type()->asNamedType()) { LookupContext symbolContext(symbol, _context); - QList resolvedClasses = symbolContext.resolveClass(namedTy->name()); + const Result r(namedTy, symbol); + const QList resolvedClasses = symbolsForDotAcces(r, _context); if (resolvedClasses.count()) { foreach (Symbol *s, resolvedClasses) { addResult(s->type(), s); @@ -535,6 +537,7 @@ bool ResolveExpression::visit(ArrayAccessAST *ast) _results.clear(); const QList indexResults = operator()(ast->expression); + SymbolsForDotAccess symbolsForDotAcccess; foreach (Result p, baseResults) { FullySpecifiedType ty = p.first; @@ -548,9 +551,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast) } else if (ArrayType *arrTy = ty->asArrayType()) { addResult(arrTy->elementType(), contextSymbol); } else if (NamedType *namedTy = ty->asNamedType()) { - Name *className = namedTy->name(); - const QList scopes = visibleScopes(p); - const QList classObjectCandidates = _context.resolveClass(className, scopes); + const QList classObjectCandidates = + symbolsForDotAcccess(p, _context); foreach (Symbol *classObject, classObjectCandidates) { const QList overloads = resolveArrayOperator(p, namedTy, @@ -593,6 +595,7 @@ ResolveExpression::resolveMemberExpression(const QList &baseResults, unsigned accessOp, Name *memberName) const { + SymbolsForDotAccess symbolsForDotAccess; QList results; if (accessOp == T_ARROW) { @@ -603,9 +606,8 @@ ResolveExpression::resolveMemberExpression(const QList &baseResults, ty = refTy->elementType(); if (NamedType *namedTy = ty->asNamedType()) { - Name *className = namedTy->name(); - const QList scopes = visibleScopes(p); - const QList classObjectCandidates = _context.resolveClass(className, scopes); + const QList classObjectCandidates = + symbolsForDotAccess(namedTy, p, _context); foreach (Symbol *classObject, classObjectCandidates) { const QList overloads = resolveArrowOperator(p, namedTy, @@ -665,12 +667,15 @@ ResolveExpression::resolveMember(const Result &p, Name *memberName, NamedType *namedTy) const { + SymbolsForDotAccess symbolsForDotAccess; + + const QList classObjectCandidates = + symbolsForDotAccess(namedTy, p, _context); + QList results; - Name *className = namedTy->name(); - const QList scopes = visibleScopes(p); - const QList classObjectCandidates = _context.resolveClass(className, scopes); foreach (Symbol *classObject, classObjectCandidates) { - results += resolveMember(p, memberName, namedTy, classObject->asClass()); + results += resolveMember(p, memberName, namedTy, + classObject->asClass()); } return results; } From c7b023c0e102419400d44e802fab36dcf3eb14c0 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 30 Dec 2008 12:03:49 +0100 Subject: [PATCH 097/230] Renamed SymbolsForDotAccess to ResolveClass. --- src/libs/cplusplus/ResolveExpression.cpp | 34 +++++++++++----------- src/libs/cplusplus/ResolveExpression.h | 8 ++--- src/plugins/cpptools/cppcodecompletion.cpp | 26 ++++++++--------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 8653d7820f6..5c656f3d57c 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -427,7 +427,7 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast) bool ResolveExpression::visit(QualifiedNameAST *ast) { - SymbolsForDotAccess symbolsForDotAcces; + ResolveClass symbolsForDotAcces; Scope dummy; Name *name = sem.check(ast, &dummy); @@ -537,7 +537,7 @@ bool ResolveExpression::visit(ArrayAccessAST *ast) _results.clear(); const QList indexResults = operator()(ast->expression); - SymbolsForDotAccess symbolsForDotAcccess; + ResolveClass symbolsForDotAcccess; foreach (Result p, baseResults) { FullySpecifiedType ty = p.first; @@ -595,7 +595,7 @@ ResolveExpression::resolveMemberExpression(const QList &baseResults, unsigned accessOp, Name *memberName) const { - SymbolsForDotAccess symbolsForDotAccess; + ResolveClass resolveClass; QList results; if (accessOp == T_ARROW) { @@ -607,7 +607,7 @@ ResolveExpression::resolveMemberExpression(const QList &baseResults, if (NamedType *namedTy = ty->asNamedType()) { const QList classObjectCandidates = - symbolsForDotAccess(namedTy, p, _context); + resolveClass(namedTy, p, _context); foreach (Symbol *classObject, classObjectCandidates) { const QList overloads = resolveArrowOperator(p, namedTy, @@ -667,10 +667,10 @@ ResolveExpression::resolveMember(const Result &p, Name *memberName, NamedType *namedTy) const { - SymbolsForDotAccess symbolsForDotAccess; + ResolveClass resolveClass; const QList classObjectCandidates = - symbolsForDotAccess(namedTy, p, _context); + resolveClass(namedTy, p, _context); QList results; foreach (Symbol *classObject, classObjectCandidates) { @@ -799,29 +799,29 @@ bool ResolveExpression::visit(PostIncrDecrAST *) } //////////////////////////////////////////////////////////////////////////////// -SymbolsForDotAccess::SymbolsForDotAccess() +ResolveClass::ResolveClass() { } -QList SymbolsForDotAccess::operator()(NamedType *namedTy, +QList ResolveClass::operator()(NamedType *namedTy, ResolveExpression::Result p, const LookupContext &context) { const QList previousBlackList = _blackList; - const QList symbols = symbolsForDotAccess(namedTy, p, context); + const QList symbols = resolveClass(namedTy, p, context); _blackList = previousBlackList; return symbols; } -QList SymbolsForDotAccess::operator()(ResolveExpression::Result p, +QList ResolveClass::operator()(ResolveExpression::Result p, const LookupContext &context) { const QList previousBlackList = _blackList; - const QList symbols = symbolsForDotAccess(p, context); + const QList symbols = resolveClass(p, context); _blackList = previousBlackList; return symbols; } -QList SymbolsForDotAccess::symbolsForDotAccess(NamedType *namedTy, +QList ResolveClass::resolveClass(NamedType *namedTy, ResolveExpression::Result p, const LookupContext &context) { @@ -852,7 +852,7 @@ QList SymbolsForDotAccess::symbolsForDotAccess(NamedType *namedTy, // Boh b; // b. const ResolveExpression::Result r(decl->type(), decl); - resolvedSymbols += symbolsForDotAccess(r, context); + resolvedSymbols += resolveClass(r, context); } } } else if (Declaration *decl = candidate->asDeclaration()) { @@ -861,7 +861,7 @@ QList SymbolsForDotAccess::symbolsForDotAccess(NamedType *namedTy, // foo. if (funTy->scope()->isBlockScope() || funTy->scope()->isNamespaceScope()) { const ResolveExpression::Result r(funTy->returnType(), decl); - resolvedSymbols += symbolsForDotAccess(r, context); + resolvedSymbols += resolveClass(r, context); } } } @@ -870,16 +870,16 @@ QList SymbolsForDotAccess::symbolsForDotAccess(NamedType *namedTy, return resolvedSymbols; } -QList SymbolsForDotAccess::symbolsForDotAccess(ResolveExpression::Result p, +QList ResolveClass::resolveClass(ResolveExpression::Result p, const LookupContext &context) { FullySpecifiedType ty = p.first; if (NamedType *namedTy = ty->asNamedType()) { - return symbolsForDotAccess(namedTy, p, context); + return resolveClass(namedTy, p, context); } else if (ReferenceType *refTy = ty->asReferenceType()) { const ResolveExpression::Result e(refTy->elementType(), p.second); - return symbolsForDotAccess(e, context); + return resolveClass(e, context); } return QList(); diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index ff98b7344d7..e7cf1c0a3af 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -128,10 +128,10 @@ private: QList _results; }; -class CPLUSPLUS_EXPORT SymbolsForDotAccess +class CPLUSPLUS_EXPORT ResolveClass { public: - SymbolsForDotAccess(); + ResolveClass(); QList operator()(NamedType *namedTy, ResolveExpression::Result p, @@ -141,11 +141,11 @@ public: const LookupContext &context); private: - QList symbolsForDotAccess(NamedType *namedTy, + QList resolveClass(NamedType *namedTy, ResolveExpression::Result p, const LookupContext &context); - QList symbolsForDotAccess(ResolveExpression::Result p, + QList resolveClass(ResolveExpression::Result p, const LookupContext &context); private: diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index ab389d0a3b3..5ceecf91482 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -592,10 +592,9 @@ bool CppCodeCompletion::completeMember(const QList &re if (NamedType *namedTy = ty->asNamedType()) { ResolveExpression resolveExpression(context); - SymbolsForDotAccess symbolsForDotAccess; + ResolveClass resolveClass; - const QList candidates = symbolsForDotAccess(namedTy, p, - context); + const QList candidates = resolveClass(namedTy, p, context); foreach (Symbol *classObject, candidates) { const QList overloads = @@ -616,7 +615,7 @@ bool CppCodeCompletion::completeMember(const QList &re if (PointerType *ptrTy = ty->asPointerType()) { if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { const QList classes = - symbolsForDotAccess(namedTy, p, context); + resolveClass(namedTy, p, context); foreach (Symbol *c, classes) { if (! classObjectCandidates.contains(c)) @@ -628,9 +627,9 @@ bool CppCodeCompletion::completeMember(const QList &re } } else if (PointerType *ptrTy = ty->asPointerType()) { if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { - SymbolsForDotAccess symbolsForDotAccess; + ResolveClass resolveClass; - const QList classes = symbolsForDotAccess(namedTy, p, + const QList classes = resolveClass(namedTy, p, context); foreach (Symbol *c, classes) { @@ -663,8 +662,8 @@ bool CppCodeCompletion::completeMember(const QList &re } if (namedTy) { - SymbolsForDotAccess symbolsForDotAccess; - const QList symbols = symbolsForDotAccess(namedTy, p, context); + ResolveClass resolveClass; + const QList symbols = resolveClass(namedTy, p, context); foreach (Symbol *symbol, symbols) { if (classObjectCandidates.contains(symbol)) continue; @@ -715,8 +714,8 @@ bool CppCodeCompletion::completeScope(const QList &res completeClass(candidates, context); } else if (Symbol *symbol = result.second) { if (symbol->isTypedef()) { - SymbolsForDotAccess symbolsForDotAccess; - const QList candidates = symbolsForDotAccess(result, + ResolveClass resolveClass; + const QList candidates = resolveClass(result, context); completeClass(candidates, context); } @@ -829,6 +828,8 @@ bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, if (results.isEmpty()) return false; + ResolveClass resolveClass; + ConvertToCompletionItem toCompletionItem(this); Overview o; o.setShowReturnTypes(false); @@ -849,10 +850,8 @@ bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, if (! namedTy) // not a class name. continue; - const QList visibleScopes = context.visibleScopes(p); - const QList classObjects = - context.resolveClass(namedTy->name(), visibleScopes); + resolveClass(namedTy, p, context); if (classObjects.isEmpty()) continue; @@ -860,6 +859,7 @@ bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, Class *klass = classObjects.first()->asClass(); QList todo; + const QList visibleScopes = context.visibleScopes(p); context.expand(klass->members(), visibleScopes, &todo); foreach (Scope *scope, todo) { From c7ac64e7de90a95b0249ce1b3c26c7a324812df8 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 31 Dec 2008 10:47:02 +0100 Subject: [PATCH 098/230] Test typedefs and pointers to anonymous structs. --- .../auto/cplusplus/semantic/tst_semantic.cpp | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 41d7a71d144..2da819d5af7 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -97,6 +97,7 @@ private slots: void nested_class_1(); void typedef_1(); void typedef_2(); + void typedef_3(); }; void tst_Semantic::function_declaration_1() @@ -295,5 +296,28 @@ void tst_Semantic::typedef_2() QVERIFY(mainFun); } +void tst_Semantic::typedef_3() +{ + QSharedPointer doc = document( +"typedef struct {\n" +" int x, y;\n" +"} *PointPtr;\n" + ); + + QCOMPARE(doc->errorCount, 0U); + QCOMPARE(doc->globals->symbolCount(), 2U); + + Class *_pointStruct= doc->globals->symbolAt(0)->asClass(); + QVERIFY(_pointStruct); + QCOMPARE(_pointStruct->memberCount(), 2U); + + Declaration *typedefPointDecl = doc->globals->symbolAt(1)->asDeclaration(); + QVERIFY(typedefPointDecl); + QVERIFY(typedefPointDecl->isTypedef()); + QVERIFY(typedefPointDecl->type()->isPointerType()); + QCOMPARE(typedefPointDecl->type()->asPointerType()->elementType()->asClass(), + _pointStruct); +} + QTEST_APPLESS_MAIN(tst_Semantic) #include "tst_semantic.moc" From f0ac751f4a167f2b2da5a21f8c62394c4486d268 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 31 Dec 2008 10:57:27 +0100 Subject: [PATCH 099/230] Completion for typedef of pointer to struct. --- src/libs/cplusplus/LookupContext.cpp | 4 ++- src/libs/cplusplus/ResolveExpression.cpp | 21 ++++++------ src/plugins/cpptools/cppcodecompletion.cpp | 38 ++++++++++++++++------ 3 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 2b787a9e11c..bf5df8b499b 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -32,13 +32,15 @@ ***************************************************************************/ #include "LookupContext.h" +#include "ResolveExpression.h" +#include "Overview.h" + #include #include #include #include #include #include -#include #include diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 5c656f3d57c..6f8ae2ba9b9 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -427,7 +427,7 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast) bool ResolveExpression::visit(QualifiedNameAST *ast) { - ResolveClass symbolsForDotAcces; + ResolveClass resolveClass; Scope dummy; Name *name = sem.check(ast, &dummy); @@ -437,7 +437,8 @@ bool ResolveExpression::visit(QualifiedNameAST *ast) if (NamedType *namedTy = symbol->type()->asNamedType()) { LookupContext symbolContext(symbol, _context); const Result r(namedTy, symbol); - const QList resolvedClasses = symbolsForDotAcces(r, _context); + const QList resolvedClasses = + resolveClass(r, _context); if (resolvedClasses.count()) { foreach (Symbol *s, resolvedClasses) { addResult(s->type(), s); @@ -555,8 +556,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast) symbolsForDotAcccess(p, _context); foreach (Symbol *classObject, classObjectCandidates) { - const QList overloads = resolveArrayOperator(p, namedTy, - classObject->asClass()); + const QList overloads = + resolveArrayOperator(p, namedTy, classObject->asClass()); foreach (Result r, overloads) { FullySpecifiedType ty = r.first; Function *funTy = ty->asFunction(); @@ -803,8 +804,8 @@ ResolveClass::ResolveClass() { } QList ResolveClass::operator()(NamedType *namedTy, - ResolveExpression::Result p, - const LookupContext &context) + ResolveExpression::Result p, + const LookupContext &context) { const QList previousBlackList = _blackList; const QList symbols = resolveClass(namedTy, p, context); @@ -813,7 +814,7 @@ QList ResolveClass::operator()(NamedType *namedTy, } QList ResolveClass::operator()(ResolveExpression::Result p, - const LookupContext &context) + const LookupContext &context) { const QList previousBlackList = _blackList; const QList symbols = resolveClass(p, context); @@ -822,8 +823,8 @@ QList ResolveClass::operator()(ResolveExpression::Result p, } QList ResolveClass::resolveClass(NamedType *namedTy, - ResolveExpression::Result p, - const LookupContext &context) + ResolveExpression::Result p, + const LookupContext &context) { QList resolvedSymbols; @@ -871,7 +872,7 @@ QList ResolveClass::resolveClass(NamedType *namedTy, } QList ResolveClass::resolveClass(ResolveExpression::Result p, - const LookupContext &context) + const LookupContext &context) { FullySpecifiedType ty = p.first; diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 5ceecf91482..50e5432f2f8 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -581,24 +581,36 @@ bool CppCodeCompletion::completeMember(const QList &re if (results.isEmpty()) return false; - const TypeOfExpression::Result p = results.first(); + TypeOfExpression::Result result = results.first(); QList classObjectCandidates; if (m_completionOperator == T_ARROW) { - FullySpecifiedType ty = p.first; + FullySpecifiedType ty = result.first; if (ReferenceType *refTy = ty->asReferenceType()) ty = refTy->elementType(); + if (NamedType *namedTy = ty->asNamedType()) { + // ### This code is pretty slow. + const QList candidates = context.resolve(namedTy->name()); + foreach (Symbol *candidate, candidates) { + if (candidate->isTypedef()) { + ty = candidate->type(); + const ResolveExpression::Result r(ty, candidate); + result = r; + break; + } + } + } + if (NamedType *namedTy = ty->asNamedType()) { ResolveExpression resolveExpression(context); ResolveClass resolveClass; - const QList candidates = resolveClass(namedTy, p, context); - + const QList candidates = resolveClass(result, context); foreach (Symbol *classObject, candidates) { const QList overloads = - resolveExpression.resolveArrowOperator(p, namedTy, + resolveExpression.resolveArrowOperator(result, namedTy, classObject->asClass()); foreach (TypeOfExpression::Result r, overloads) { @@ -615,7 +627,7 @@ bool CppCodeCompletion::completeMember(const QList &re if (PointerType *ptrTy = ty->asPointerType()) { if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { const QList classes = - resolveClass(namedTy, p, context); + resolveClass(namedTy, result, context); foreach (Symbol *c, classes) { if (! classObjectCandidates.contains(c)) @@ -629,17 +641,22 @@ bool CppCodeCompletion::completeMember(const QList &re if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { ResolveClass resolveClass; - const QList classes = resolveClass(namedTy, p, - context); + const QList classes = resolveClass(namedTy, result, + context); foreach (Symbol *c, classes) { if (! classObjectCandidates.contains(c)) classObjectCandidates.append(c); } + } else if (Class *classTy = ptrTy->elementType()->asClass()) { + // typedef struct { int x } *Ptr; + // Ptr p; + // p-> + classObjectCandidates.append(classTy); } } } else if (m_completionOperator == T_DOT) { - FullySpecifiedType ty = p.first; + FullySpecifiedType ty = result.first; if (ReferenceType *refTy = ty->asReferenceType()) ty = refTy->elementType(); @@ -663,7 +680,8 @@ bool CppCodeCompletion::completeMember(const QList &re if (namedTy) { ResolveClass resolveClass; - const QList symbols = resolveClass(namedTy, p, context); + const QList symbols = resolveClass(namedTy, result, + context); foreach (Symbol *symbol, symbols) { if (classObjectCandidates.contains(symbol)) continue; From bdf1800d83eef2c3940ed93466d3387fe2e172ee Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 16:10:00 +0100 Subject: [PATCH 100/230] Added `colon_token' to ClassSpecifierAST. --- shared/cplusplus/AST.h | 1 + shared/cplusplus/Parser.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/shared/cplusplus/AST.h b/shared/cplusplus/AST.h index c4b0f7fe76f..f9960f80d78 100644 --- a/shared/cplusplus/AST.h +++ b/shared/cplusplus/AST.h @@ -444,6 +444,7 @@ public: unsigned classkey_token; SpecifierAST *attributes; NameAST *name; + unsigned colon_token; BaseSpecifierAST *base_clause; unsigned lbrace_token; DeclarationAST *member_specifiers; diff --git a/shared/cplusplus/Parser.cpp b/shared/cplusplus/Parser.cpp index 549a74ce111..05836e9fca0 100644 --- a/shared/cplusplus/Parser.cpp +++ b/shared/cplusplus/Parser.cpp @@ -1196,9 +1196,12 @@ bool Parser::parseClassSpecifier(SpecifierAST *&node) const bool previousInFunctionBody = _inFunctionBody; _inFunctionBody = false; + unsigned colon_token = 0; + if (LA() == T_COLON || LA() == T_LBRACE) { BaseSpecifierAST *base_clause = 0; if (LA() == T_COLON) { + colon_token = cursor(); parseBaseClause(base_clause); if (LA() != T_LBRACE) { _translationUnit->error(cursor(), "expected `{' before `%s'", tok().spell()); @@ -1216,6 +1219,7 @@ bool Parser::parseClassSpecifier(SpecifierAST *&node) ast->classkey_token = classkey_token; ast->attributes = attributes; ast->name = name; + ast->colon_token = colon_token; ast->base_clause = base_clause; if (LA() == T_LBRACE) From a886a63077520f3cb2cf8e338a0bee7f8dea5b6e Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 16:10:28 +0100 Subject: [PATCH 101/230] Playing with the AST rewriter. --- tests/manual/cplusplus/main.cpp | 154 +++++++++++++++++++++++++++++--- 1 file changed, 143 insertions(+), 11 deletions(-) diff --git a/tests/manual/cplusplus/main.cpp b/tests/manual/cplusplus/main.cpp index 641c25366c8..e5a68d40586 100644 --- a/tests/manual/cplusplus/main.cpp +++ b/tests/manual/cplusplus/main.cpp @@ -32,40 +32,172 @@ ***************************************************************************/ #include +#include #include #include #include #include #include +#include +#include #include #include +class Rewrite +{ + QMultiMap _insertBefore; + QMultiMap _insertAfter; + QSet _removed; + +public: + void remove(unsigned index) + { remove(index, index + 1); } + + void remove(unsigned first, unsigned last) + { + Q_ASSERT(first < last); + + for (; first != last; ++first) + _removed.insert(first); + } + + void insertTextBefore(unsigned index, const QByteArray &text) + { _insertBefore.insert(index, text); } + + void insertTextAfter(unsigned index, const QByteArray &text) + { _insertAfter.insert(index, text); } + + void rewrite(const TranslationUnit *unit, + const QByteArray &contents, + QByteArray *out) const + { + const char *source = contents.constData(); + unsigned previousTokenEndPosition = 0; + for (unsigned i = 0; i < unit->tokenCount(); ++i) { + const Token &tk = unit->tokenAt(i); + + if (previousTokenEndPosition != tk.begin()) { + Q_ASSERT(previousTokenEndPosition < tk.begin()); + out->append(source + previousTokenEndPosition, + tk.begin() - previousTokenEndPosition); + } + + QMultiMap::const_iterator it; + + it = _insertBefore.constFind(i); + for (; it != _insertBefore.constEnd() && it.key() == i; ++it) { + out->append(it.value()); + } + + if (! _removed.contains(i)) + out->append(source + tk.begin(), tk.length); + + it = _insertAfter.constFind(i); + for (; it != _insertAfter.constEnd() && it.key() == i; ++it) { + out->append(it.value()); + } + + previousTokenEndPosition = tk.end(); + } + } +}; + +class SimpleRefactor: protected ASTVisitor, Rewrite { +public: + SimpleRefactor(Control *control) + : ASTVisitor(control) + { } + + void operator()(const TranslationUnit *unit, + const QByteArray &source, + QByteArray *out) + { + accept(unit->ast()); + rewrite(unit, source, out); + } + +protected: + virtual bool visit(AccessDeclarationAST *ast) + { + if (tokenKind(ast->access_specifier_token) == T_PRIVATE) { + // change visibility from `private' to `public'. + remove(ast->access_specifier_token); + insertTextAfter(ast->access_specifier_token, "public /* #REF# private->public */"); + } + return true; + } + + virtual bool visit(FunctionDefinitionAST *ast) + { + bool isInline = false; + for (SpecifierAST *spec = ast->decl_specifier_seq; spec; spec = spec->next) { + if (SimpleSpecifierAST *simpleSpec = spec->asSimpleSpecifier()) { + if (tokenKind(simpleSpec->specifier_token) == T_INLINE) { + isInline = true; + break; + } + } + } + + // force the `inline' specifier. + if (! isInline) + insertTextBefore(ast->firstToken(), "inline /* #REF# made inline */ "); + + return true; + } + + virtual bool visit(ClassSpecifierAST *ast) + { + // export/import the class using the macro MY_EXPORT. + if (ast->name) + insertTextBefore(ast->name->firstToken(), "MY_EXPORT "); + + // add QObject to the base clause. + if (ast->colon_token) + insertTextAfter(ast->colon_token, " public QObject,"); + else if (ast->lbrace_token) + insertTextBefore(ast->lbrace_token, ": public QObject "); + + // mark the class as Q_OBJECT. + if (ast->lbrace_token) + insertTextAfter(ast->lbrace_token, " Q_OBJECT\n"); + + return true; + } +}; + int main(int, char *[]) { - Control control; - StringLiteral *fileId = control.findOrInsertFileName(""); - QFile in; if (! in.open(stdin, QFile::ReadOnly)) return EXIT_FAILURE; const QByteArray source = in.readAll(); + Control control; + StringLiteral *fileId = control.findOrInsertFileName(""); TranslationUnit unit(&control, fileId); unit.setSource(source.constData(), source.size()); unit.parse(); - if (unit.ast()) { - TranslationUnitAST *ast = unit.ast()->asTranslationUnit(); - Q_ASSERT(ast != 0); + if (! unit.ast()) + return EXIT_FAILURE; - Scope globalScope; - Semantic sem(&control); - for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) { - sem.check(decl, &globalScope); - } + TranslationUnitAST *ast = unit.ast()->asTranslationUnit(); + Q_ASSERT(ast != 0); + + Scope globalScope; + Semantic sem(&control); + for (DeclarationAST *decl = ast->declarations; decl; decl = decl->next) { + sem.check(decl, &globalScope); } + // test the rewriter + QByteArray out; + SimpleRefactor refactor(&control); + refactor(&unit, source, &out); + printf("%s\n", out.constData()); + return EXIT_SUCCESS; } From e89ec6c3fa287846df987ced8ae2b2d6e60944c0 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 16:47:35 +0100 Subject: [PATCH 102/230] Fixed SimpleDeclarationAST::firstToken(). --- shared/cplusplus/AST.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 7774d4d71fa..c495ea18816 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1940,15 +1940,12 @@ void SimpleDeclarationAST::accept0(ASTVisitor *visitor) unsigned SimpleDeclarationAST::firstToken() const { - for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) { - if (! it->next) - return it->firstToken(); - } - for (DeclaratorListAST *it = declarators; it; it = it->next) { - if (! it->next) - return it->firstToken(); - } - return semicolon_token; + if (decl_specifier_seq) + return decl_specifier_seq->firstToken(); + else if (declarators) + return declarators->firstToken(); + else + return semicolon_token; } unsigned SimpleDeclarationAST::lastToken() const From 4d352e369b063fa9a2f4e20609284f49f71a2689 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 17:36:08 +0100 Subject: [PATCH 103/230] Initial work on *AST::lastToken(). --- shared/cplusplus/AST.cpp | 247 ++++++++++++++++++++++++++++++--------- shared/cplusplus/AST.h | 2 +- 2 files changed, 194 insertions(+), 55 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index c495ea18816..fa41bf56630 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -395,14 +395,17 @@ unsigned AttributeSpecifierAST::firstToken() const unsigned AttributeSpecifierAST::lastToken() const { - assert(0 && "review me"); if (second_rparen_token) return second_rparen_token + 1; else if (first_rparen_token) return first_rparen_token + 1; else if (attributes) return attributes->lastToken(); - return second_lparen_token + 1; + else if (second_lparen_token) + return second_lparen_token + 1; + else if (first_lparen_token) + return first_lparen_token + 1; + return attribute_token + 1; } void AttributeSpecifierAST::accept0(ASTVisitor *visitor) @@ -420,11 +423,22 @@ unsigned AttributeAST::firstToken() const unsigned AttributeAST::lastToken() const { - assert(0 && "review me"); - if (expression_list) - return expression_list->lastToken(); - else if (tag_token) + if (rparen_token) + return rparen_token + 1; + + for (ExpressionListAST *it = expression_list; + it->expression && it->next; it = it->next) { + if (! it->next && it->expression) { + return it->expression->lastToken(); + } + } + + if (tag_token) return tag_token + 1; + + if (lparen_token) + return lparen_token + 1; + return identifier_token + 1; } @@ -449,8 +463,11 @@ unsigned AccessDeclarationAST::firstToken() const unsigned AccessDeclarationAST::lastToken() const { - assert(0 && "review me"); - return colon_token + 1; + if (colon_token) + return colon_token + 1; + else if (slots_token) + return slots_token + 1; + return access_specifier_token + 1; } void ArrayAccessAST::accept0(ASTVisitor *visitor) @@ -467,8 +484,11 @@ unsigned ArrayAccessAST::firstToken() const unsigned ArrayAccessAST::lastToken() const { - assert(0 && "review me"); - return rbracket_token + 1; + if (rbracket_token) + return rbracket_token + 1; + else if (expression) + return expression->lastToken(); + return lbracket_token + 1; } void ArrayDeclaratorAST::accept0(ASTVisitor *visitor) @@ -485,8 +505,11 @@ unsigned ArrayDeclaratorAST::firstToken() const unsigned ArrayDeclaratorAST::lastToken() const { - assert(0 && "review me"); - return rbracket_token + 1; + if (rbracket_token) + return rbracket_token + 1; + else if (expression) + return expression->lastToken(); + return lbracket_token + 1; } void ArrayInitializerAST::accept0(ASTVisitor *visitor) @@ -505,8 +528,15 @@ unsigned ArrayInitializerAST::firstToken() const unsigned ArrayInitializerAST::lastToken() const { - assert(0 && "review me"); - return rbrace_token + 1; + if (rbrace_token) + return rbrace_token + 1; + + for (ExpressionListAST *it = expression_list; it; it = it->next) { + if (! it->next && it->expression) + return it->expression->lastToken(); + } + + return lbrace_token + 1; } void AsmDefinitionAST::accept0(ASTVisitor *visitor) @@ -525,8 +555,18 @@ unsigned AsmDefinitionAST::firstToken() const unsigned AsmDefinitionAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + else if (rparen_token) + return rparen_token + 1; + else if (lparen_token) + return lparen_token + 1; + for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return asm_token + 1; } void BaseSpecifierAST::accept0(ASTVisitor *visitor) @@ -545,8 +585,16 @@ unsigned BaseSpecifierAST::firstToken() const unsigned BaseSpecifierAST::lastToken() const { - assert(0 && "review me"); - return name->lastToken(); + if (name) + return name->lastToken(); + else if (token_virtual && token_access_specifier) + return std::min(token_virtual, token_access_specifier) + 1; + else if (token_virtual) + return token_virtual + 1; + else if (token_access_specifier) + return token_access_specifier + 1; + // assert? + return 0; } unsigned QtMethodAST::firstToken() const @@ -554,8 +602,13 @@ unsigned QtMethodAST::firstToken() const unsigned QtMethodAST::lastToken() const { - assert(0 && "review me"); - return rparen_token; + if (rparen_token) + return rparen_token + 1; + else if (declarator) + return declarator->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return method_token + 1; } void QtMethodAST::accept0(ASTVisitor *visitor) @@ -580,8 +633,11 @@ unsigned BinaryExpressionAST::firstToken() const unsigned BinaryExpressionAST::lastToken() const { - assert(0 && "review me"); - return right_expression->lastToken(); + if (right_expression) + return right_expression->lastToken(); + else if (binary_op_token) + return binary_op_token + 1; + return left_expression->lastToken(); } void BoolLiteralAST::accept0(ASTVisitor *visitor) @@ -597,7 +653,6 @@ unsigned BoolLiteralAST::firstToken() const unsigned BoolLiteralAST::lastToken() const { - assert(0 && "review me"); return token + 1; } @@ -614,8 +669,9 @@ unsigned BreakStatementAST::firstToken() const unsigned BreakStatementAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + return break_token + 1; } void CallAST::accept0(ASTVisitor *visitor) @@ -634,8 +690,13 @@ unsigned CallAST::firstToken() const unsigned CallAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + for (ExpressionListAST *it = expression_list; it; it = it->next) { + if (! it->next && it->expression) + return it->expression->lastToken(); + } + return lparen_token + 1; } void CaseStatementAST::accept0(ASTVisitor *visitor) @@ -651,10 +712,13 @@ unsigned CaseStatementAST::firstToken() const unsigned CaseStatementAST::lastToken() const { - assert(0 && "review me"); if (statement) return statement->lastToken(); - return colon_token + 1; + else if (colon_token) + return colon_token + 1; + else if (expression) + return expression->lastToken(); + return case_token + 1; } void CastExpressionAST::accept0(ASTVisitor *visitor) @@ -670,8 +734,13 @@ unsigned CastExpressionAST::firstToken() const unsigned CastExpressionAST::lastToken() const { - assert(0 && "review me"); - return expression->lastToken(); + if (expression) + return expression->lastToken(); + else if (rparen_token) + return rparen_token + 1; + else if (type_id) + return type_id->lastToken(); + return lparen_token + 1; } void CatchClauseAST::accept0(ASTVisitor *visitor) @@ -689,10 +758,18 @@ unsigned CatchClauseAST::firstToken() const unsigned CatchClauseAST::lastToken() const { - assert(0 && "review me"); if (statement) return statement->lastToken(); - return rparen_token + 1; + else if (rparen_token) + return rparen_token + 1; + for (DeclarationAST *it = exception_declaration; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + if (lparen_token) + return lparen_token + 1; + + return catch_token + 1; } void ClassSpecifierAST::accept0(ASTVisitor *visitor) @@ -715,8 +792,34 @@ unsigned ClassSpecifierAST::firstToken() const unsigned ClassSpecifierAST::lastToken() const { - assert(0 && "review me"); - return rbrace_token + 1; + if (rbrace_token) + return rbrace_token + 1; + + for (DeclarationAST *it = member_specifiers; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (lbrace_token) + return lbrace_token + 1; + + for (BaseSpecifierAST *it = base_clause; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (colon_token) + return colon_token + 1; + + if (name) + return name->lastToken(); + + for (SpecifierAST *it = attributes; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return classkey_token + 1; } void CompoundStatementAST::accept0(ASTVisitor *visitor) @@ -734,8 +837,15 @@ unsigned CompoundStatementAST::firstToken() const unsigned CompoundStatementAST::lastToken() const { - assert(0 && "review me"); - return rbrace_token + 1; + if (rbrace_token) + return rbrace_token + 1; + + for (StatementAST *it = statements; it ; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return lbrace_token + 1; } void ConditionAST::accept0(ASTVisitor *visitor) @@ -751,13 +861,22 @@ unsigned ConditionAST::firstToken() const { if (type_specifier) return type_specifier->firstToken(); + return declarator->firstToken(); } unsigned ConditionAST::lastToken() const { - assert(0 && "review me"); - return declarator->lastToken(); + if (declarator) + return declarator->lastToken(); + + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + // ### assert? + return 0; } void ConditionalExpressionAST::accept0(ASTVisitor *visitor) @@ -776,10 +895,18 @@ unsigned ConditionalExpressionAST::firstToken() const unsigned ConditionalExpressionAST::lastToken() const { - assert(0 && "review me"); if (right_expression) return right_expression->lastToken(); - return colon_token + 1; + else if (colon_token) + return colon_token + 1; + else if (left_expression) + return left_expression->lastToken(); + else if (question_token) + return question_token + 1; + else if (condition) + return condition->lastToken(); + // ### assert? + return 0; } void ContinueStatementAST::accept0(ASTVisitor *visitor) @@ -795,8 +922,9 @@ unsigned ContinueStatementAST::firstToken() const unsigned ContinueStatementAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + return continue_token + 1; } void ConversionFunctionIdAST::accept0(ASTVisitor *visitor) @@ -817,16 +945,16 @@ unsigned ConversionFunctionIdAST::firstToken() const unsigned ConversionFunctionIdAST::lastToken() const { - assert(0 && "review me"); -#if 0 // ### implement me - for (DeclaratorAST *ptr_op = ptr_operators; ptr_op; - ptr_op = ptr_op->next) { - if (! ptr_op->next) - return ptr_op->lastToken(); + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { + if (! it->next) + return it->lastToken(); } -#endif - if (type_specifier) - return type_specifier->lastToken(); + + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + return operator_token + 1; } @@ -845,8 +973,19 @@ unsigned CppCastExpressionAST::firstToken() const unsigned CppCastExpressionAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (lparen_token) + return lparen_token + 1; + else if (greater_token) + return greater_token + 1; + else if (type_id) + return type_id->lastToken(); + else if (less_token) + return less_token + 1; + return cast_token + 1; } void CtorInitializerAST::accept0(ASTVisitor *visitor) diff --git a/shared/cplusplus/AST.h b/shared/cplusplus/AST.h index f9960f80d78..be4f26d9f9c 100644 --- a/shared/cplusplus/AST.h +++ b/shared/cplusplus/AST.h @@ -410,8 +410,8 @@ protected: class CPLUSPLUS_EXPORT BinaryExpressionAST: public ExpressionAST { public: - unsigned binary_op_token; ExpressionAST *left_expression; + unsigned binary_op_token; ExpressionAST *right_expression; public: From 698ec21284c4164878fda28ee944b48cd2fad7fd Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 17:42:34 +0100 Subject: [PATCH 104/230] Implemented DeclaratorAST::firstToken(), and DeclaratorAST::lastToken(). --- shared/cplusplus/AST.cpp | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index fa41bf56630..b21dc4e302e 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1004,11 +1004,10 @@ unsigned CtorInitializerAST::firstToken() const unsigned CtorInitializerAST::lastToken() const { - assert(0 && "review me"); - for (MemInitializerAST *it = member_initializers; it; - it = it->next) + for (MemInitializerAST *it = member_initializers; it; it = it->next) { if (! it->next) return it->lastToken(); + } return colon_token + 1; } @@ -1035,22 +1034,38 @@ unsigned DeclaratorAST::firstToken() const return core_declarator->firstToken(); else if (postfix_declarators) return postfix_declarators->firstToken(); + else if (attributes) + return attributes->firstToken(); + else if (initializer) + return initializer->firstToken(); + // ### assert? return 0; } unsigned DeclaratorAST::lastToken() const { - assert(0 && "review me"); - for (PostfixDeclaratorAST *fx = postfix_declarators; fx; fx = fx->next) { - if (! fx->next) - return fx->lastToken(); + if (initializer) + return initializer->lastToken(); + + for (SpecifierAST *it = attributes; it; it = it->next) { + if (! it->next) + return it->lastToken(); } + + for (PostfixDeclaratorAST *it = postfix_declarators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + if (core_declarator) return core_declarator->lastToken(); - for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op; ptr_op = ptr_op->next) { - if (! ptr_op->next) - return ptr_op->lastToken(); + + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { + if (! it->next) + return it->lastToken(); } + + // ### assert? return 0; } From f32c63abd2d4319f5254ddf630f72186d66787ae Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 17:48:31 +0100 Subject: [PATCH 105/230] Implemented DeleteExpressionAST::lastToken(). --- shared/cplusplus/AST.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index b21dc4e302e..5bfecfc9dae 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1083,7 +1083,6 @@ unsigned DeclarationStatementAST::firstToken() const unsigned DeclarationStatementAST::lastToken() const { - assert(0 && "review me"); return declaration->lastToken(); } @@ -1101,7 +1100,6 @@ unsigned DeclaratorIdAST::firstToken() const unsigned DeclaratorIdAST::lastToken() const { - assert(0 && "review me"); return name->lastToken(); } @@ -1120,7 +1118,6 @@ unsigned DeclaratorListAST::firstToken() const unsigned DeclaratorListAST::lastToken() const { - assert(0 && "review me"); for (const DeclaratorListAST *it = this; it; it = it->next) { if (! it->next) return it->lastToken(); @@ -1144,12 +1141,15 @@ unsigned DeleteExpressionAST::firstToken() const unsigned DeleteExpressionAST::lastToken() const { - assert(0 && "review me"); if (expression) return expression->lastToken(); else if (rbracket_token) return rbracket_token + 1; - return delete_token + 1; + else if (lbracket_token) + return lbracket_token + 1; + else if (delete_token) + return delete_token + 1; + return scope_token + 1; } void DestructorNameAST::accept0(ASTVisitor *visitor) From 847f7f9cd10b6c1e6b5a89545b42bf0f08f6fd1c Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 17:49:33 +0100 Subject: [PATCH 106/230] Implemented DestructorNameAST::lastToken(). --- shared/cplusplus/AST.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 5bfecfc9dae..46c14159f9f 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1165,8 +1165,9 @@ unsigned DestructorNameAST::firstToken() const unsigned DestructorNameAST::lastToken() const { - assert(0 && "review me"); - return identifier_token + 1; + if (identifier_token) + return identifier_token + 1; + return tilde_token + 1; } void DoStatementAST::accept0(ASTVisitor *visitor) From a5e9e19e59ca84511fa588e69aaa1d8b1566ab51 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 17:51:48 +0100 Subject: [PATCH 107/230] Implemented DoStatementAST::lastToken(). --- shared/cplusplus/AST.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 46c14159f9f..b6d8f29d2c3 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1185,8 +1185,19 @@ unsigned DoStatementAST::firstToken() const unsigned DoStatementAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + else if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (lparen_token) + return lparen_token + 1; + else if (while_token) + return while_token + 1; + else if (statement) + return statement->lastToken(); + return do_token + 1; } void ElaboratedTypeSpecifierAST::accept0(ASTVisitor *visitor) From 724074f3a8a269a09c4e324a95b4875e38d12c06 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 17:54:01 +0100 Subject: [PATCH 108/230] Implemented EnumSpecifierAST::lastToken(). --- shared/cplusplus/AST.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index b6d8f29d2c3..ffcc46a6810 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1214,7 +1214,6 @@ unsigned ElaboratedTypeSpecifierAST::firstToken() const unsigned ElaboratedTypeSpecifierAST::lastToken() const { - assert(0 && "review me"); if (name) return name->lastToken(); return classkey_token + 1; @@ -1233,7 +1232,6 @@ unsigned EmptyDeclarationAST::firstToken() const unsigned EmptyDeclarationAST::lastToken() const { - assert(0 && "review me"); return semicolon_token + 1; } @@ -1254,8 +1252,20 @@ unsigned EnumSpecifierAST::firstToken() const unsigned EnumSpecifierAST::lastToken() const { - assert(0 && "review me"); - return rbrace_token + 1; + if (rbrace_token) + return rbrace_token + 1; + + for (EnumeratorAST *it = enumerators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (lbrace_token) + return lbrace_token + 1; + if (name) + return name->lastToken(); + + return enum_token + 1; } void EnumeratorAST::accept0(ASTVisitor *visitor) From 3c908d292ec46036bf8b5e06f03578c098a885d0 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 17:55:13 +0100 Subject: [PATCH 109/230] Implemented EnumeratorAST::lastToken(). --- shared/cplusplus/AST.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index ffcc46a6810..e5530723fec 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1282,10 +1282,9 @@ unsigned EnumeratorAST::firstToken() const unsigned EnumeratorAST::lastToken() const { - assert(0 && "review me"); if (expression) return expression->lastToken(); - if (equal_token) + else if (equal_token) return equal_token + 1; return identifier_token + 1; } From 61dac8c9cf0569b983c0fa204ac207c659573e06 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 17:57:28 +0100 Subject: [PATCH 110/230] Implemented ExceptionDeclarationAST::lastToken(). --- shared/cplusplus/AST.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index e5530723fec..9952aa67f2d 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1300,19 +1300,22 @@ void ExceptionDeclarationAST::accept0(ASTVisitor *visitor) unsigned ExceptionDeclarationAST::firstToken() const { - return type_specifier->firstToken(); + if (type_specifier) + return type_specifier->firstToken(); + if (declarator) + return declarator->firstToken(); + return dot_dot_dot_token; } unsigned ExceptionDeclarationAST::lastToken() const { - assert(0 && "review me"); if (dot_dot_dot_token) return dot_dot_dot_token + 1; else if (declarator) return declarator->lastToken(); for (SpecifierAST *it = type_specifier; it; it = it->next) { if (! it->next) - return type_specifier->lastToken(); + return it->lastToken(); } return 0; } From 8d91577df9b9128854ae1090802a3336c6c0668a Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Fri, 2 Jan 2009 17:59:27 +0100 Subject: [PATCH 111/230] Implemented ExceptionSpecificationAST::lastToken(). --- shared/cplusplus/AST.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 9952aa67f2d..0926323ed05 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1336,8 +1336,20 @@ unsigned ExceptionSpecificationAST::firstToken() const unsigned ExceptionSpecificationAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + + for (ExpressionListAST *it = type_ids; it; it = it->next) { + if (! it->next && it->expression) + return it->expression->lastToken(); + } + + if (dot_dot_dot_token) + return dot_dot_dot_token + 1; + else if (lparen_token) + return lparen_token + 1; + + return throw_token + 1; } void ExpressionListAST::accept0(ASTVisitor *) From 722ccd9e0d39013754e383ff4b33943b9961f580 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Sat, 3 Jan 2009 13:02:37 +0100 Subject: [PATCH 112/230] Initial implementation of the pretty printer. --- shared/cplusplus/PrettyPrinter.cpp | 1223 ++++++++++++++++++++++++++++ shared/cplusplus/PrettyPrinter.h | 162 ++++ shared/cplusplus/cplusplus.pri | 7 +- 3 files changed, 1390 insertions(+), 2 deletions(-) create mode 100644 shared/cplusplus/PrettyPrinter.cpp create mode 100644 shared/cplusplus/PrettyPrinter.h diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp new file mode 100644 index 00000000000..1cf8aad143f --- /dev/null +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -0,0 +1,1223 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ + +#include "PrettyPrinter.h" +#include "AST.h" +#include +#include + +CPLUSPLUS_USE_NAMESPACE + +PrettyPrinter::PrettyPrinter(Control *control, std::ostream &out) + : ASTVisitor(control), + out(out), + depth(0) +{ } + +void PrettyPrinter::operator()(AST *ast) +{ accept(ast); } + +void PrettyPrinter::indent() +{ ++depth; } + +void PrettyPrinter::deindent() +{ --depth; } + +void PrettyPrinter::newline() +{ out << '\n' << std::string(depth * 4, ' '); } + +bool PrettyPrinter::visit(AccessDeclarationAST *ast) +{ + deindent(); + newline(); + out << spell(ast->access_specifier_token); + if (ast->slots_token) + out << ' ' << spell(ast->slots_token); + out << ':' << std::endl; + indent(); + return false; +} + +bool PrettyPrinter::visit(ArrayAccessAST *ast) +{ + out << '['; + accept(ast->expression); + out << ']'; + return false; +} + +bool PrettyPrinter::visit(ArrayDeclaratorAST *ast) +{ + out << '['; + accept(ast->expression); + out << ']'; + return false; +} + +bool PrettyPrinter::visit(ArrayInitializerAST *ast) +{ + out << '{'; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(AsmDefinitionAST *ast) +{ + out << spell(ast->asm_token); + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + out << ' '; + accept(it); + } + out << '('; + out << "/* ### implement me */"; + out << ");"; + return false; +} + +bool PrettyPrinter::visit(AttributeSpecifierAST *ast) +{ + out << "attribute(("; + for (AttributeAST *it = ast->attributes; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + out << "))"; + return false; +} + +bool PrettyPrinter::visit(AttributeAST *ast) +{ + out << spell(ast->identifier_token); + if (ast->lparen_token) { + out << '('; + out << spell(ast->tag_token); + if (ast->expression_list) { + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + } + out << ')'; + } + return false; +} + +bool PrettyPrinter::visit(BaseSpecifierAST *ast) +{ + if (ast->token_virtual && ast->token_access_specifier) { + out << "virtual "; + out << spell(ast->token_access_specifier); + } else if (ast->token_virtual) { + out << "virtual"; + } else if (ast->token_access_specifier) { + out << spell(ast->token_access_specifier); + } + accept(ast->name); + return false; +} + +bool PrettyPrinter::visit(BinaryExpressionAST *ast) +{ + accept(ast->left_expression); + out << ' ' << spell(ast->binary_op_token) << ' '; + accept(ast->right_expression); + return false; +} + +bool PrettyPrinter::visit(BoolLiteralAST *ast) +{ + out << spell(ast->token); + return false; +} + +bool PrettyPrinter::visit(BreakStatementAST *) +{ + out << "break;"; + return false; +} + +bool PrettyPrinter::visit(CallAST *ast) +{ + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(CaseStatementAST *ast) +{ + out << "case "; + accept(ast->expression); + out << ':'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(CastExpressionAST *ast) +{ + out << '('; + accept(ast->type_id); + out << ')'; + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(CatchClauseAST *ast) +{ + out << "catch"; + out << '('; + accept(ast->exception_declaration); + out << ')'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(ClassSpecifierAST *ast) +{ + out << spell(ast->classkey_token); + out << ' '; + if (ast->attributes) { + accept(ast->attributes); + out << ' '; + } + accept(ast->name); + if (ast->colon_token) { + out << ':'; + out << ' '; + for (BaseSpecifierAST *it = ast->base_clause; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + } + out << '{'; + if (ast->member_specifiers) { + indent(); + newline(); + if (ast->member_specifiers) { + for (DeclarationAST *it = ast->member_specifiers; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + } + deindent(); + newline(); + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(CompoundStatementAST *ast) +{ + out << '{'; + if (ast->statements) { + indent(); + newline(); + for (StatementAST *it = ast->statements; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + deindent(); + newline(); + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(ConditionAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + if (ast->type_specifier) + out << ' '; + + accept(ast->declarator); + } + return false; +} + +bool PrettyPrinter::visit(ConditionalExpressionAST *ast) +{ + accept(ast->condition); + out << '?'; + accept(ast->left_expression); + out << ':'; + accept(ast->right_expression); + return false; +} + +bool PrettyPrinter::visit(ContinueStatementAST *) +{ + out << "continue"; + out << ';'; + return false; +} + +bool PrettyPrinter::visit(ConversionFunctionIdAST *ast) +{ + out << "operator"; + out << ' '; + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + } + return false; +} + +bool PrettyPrinter::visit(CppCastExpressionAST *ast) +{ + out << spell(ast->cast_token); + out << '<'; + out << ' '; + accept(ast->type_id); + out << ' '; + out << '>'; + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(CtorInitializerAST *ast) +{ + out << ':'; + out << ' '; + for (MemInitializerAST *it = ast->member_initializers; it; it = it->next) { + accept(it->name); + out << '('; + accept(it->expression); + out << ')'; + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(DeclaratorAST *ast) +{ + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + } + if (ast->core_declarator) { + if (ast->ptr_operators) + out << ' '; + accept(ast->core_declarator); + } + for (PostfixDeclaratorAST *it = ast->postfix_declarators; it; it = it->next) { + accept(it); + } + for (SpecifierAST *it = ast->attributes; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->initializer) { + out << '='; + out << ' '; + accept(ast->initializer); + } + return false; +} + +bool PrettyPrinter::visit(DeclarationStatementAST *ast) +{ + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(DeclaratorIdAST *ast) +{ + accept(ast->name); + return false; +} + +bool PrettyPrinter::visit(DeclaratorListAST *) +{ + assert(0); + return false; +} + +bool PrettyPrinter::visit(DeleteExpressionAST *ast) +{ + if (ast->scope_token) + out << "::"; + out << "delete"; + if (ast->expression) { + out << ' '; + accept(ast->expression); + } + return false; +} + +bool PrettyPrinter::visit(DestructorNameAST *ast) +{ + out << '~'; + out << spell(ast->identifier_token); + return false; +} + +bool PrettyPrinter::visit(DoStatementAST *ast) +{ + out << "do"; + if (ast->statement) { + out << ' '; + accept(ast->statement); + } + out << "while"; + out << '('; + accept(ast->expression); + out << ')'; + out << ';'; + return false; +} + +bool PrettyPrinter::visit(ElaboratedTypeSpecifierAST *ast) +{ + out << spell(ast->classkey_token); + if (ast->name) { + out << ' '; + accept(ast->name); + } + return false; +} + +bool PrettyPrinter::visit(EmptyDeclarationAST *) +{ + out << ';'; + return false; +} + +bool PrettyPrinter::visit(EnumSpecifierAST *ast) +{ + out << "enum"; + if (ast->name) { + out << ' '; + accept(ast->name); + } + out << '{'; + for (EnumeratorAST *it = ast->enumerators; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(EnumeratorAST *ast) +{ + out << spell(ast->identifier_token); + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + accept(ast->expression); + } + return false; +} + +bool PrettyPrinter::visit(ExceptionDeclarationAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + if (ast->type_specifier) + out << ' '; + accept(ast->declarator); + } + if (ast->dot_dot_dot_token) + out << "..."; + return false; +} + +bool PrettyPrinter::visit(ExceptionSpecificationAST *ast) +{ + out << "throw"; + out << '('; + if (ast->dot_dot_dot_token) + out << "..."; + else { + for (ExpressionListAST *it = ast->type_ids; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(ExpressionListAST *ast) +{ + for (ExpressionListAST *it = ast; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(ExpressionOrDeclarationStatementAST *ast) +{ + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(ExpressionStatementAST *ast) +{ + accept(ast->expression); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(ForStatementAST *ast) +{ + out << "for"; + out << ' '; + out << '('; + accept(ast->initializer); + accept(ast->condition); + out << ';'; + accept(ast->expression); + out << ')'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(FunctionDeclaratorAST *ast) +{ + out << '('; + accept(ast->parameters); + out << ')'; + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->exception_specification) { + out << ' '; + accept(ast->exception_specification); + } + return false; +} + +bool PrettyPrinter::visit(FunctionDefinitionAST *ast) +{ + for (SpecifierAST *it = ast->decl_specifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + if (ast->decl_specifier_seq) + out << ' '; + accept(ast->declarator); + } + accept(ast->ctor_initializer); + newline(); + accept(ast->function_body); + if (ast->next) + newline(); // one extra line after the function definiton. + return false; +} + +bool PrettyPrinter::visit(GotoStatementAST *ast) +{ + out << "goto"; + out << ' '; + out << spell(ast->identifier_token); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(IfStatementAST *ast) +{ + out << "if"; + out << ' '; + out << '('; + accept(ast->condition); + out << ')'; + if (ast->statement->asCompoundStatement()) + accept(ast->statement); + else { + indent(); + newline(); + accept(ast->statement); + deindent(); + newline(); + } + if (ast->else_token) { + out << "else"; + out << ' '; + accept(ast->else_statement); + } + return false; +} + +bool PrettyPrinter::visit(LabeledStatementAST *ast) +{ + out << spell(ast->label_token); + out << ':'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(LinkageBodyAST *ast) +{ + out << '{'; + if (ast->declarations) { + indent(); + newline(); + for (DeclarationAST *it = ast->declarations; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + deindent(); + newline(); + } + out << '}'; + return false; +} + +bool PrettyPrinter::visit(LinkageSpecificationAST *ast) +{ + out << "extern"; + out << ' '; + if (ast->extern_type) { + out << '"' << spell(ast->extern_type) << '"'; + out << ' '; + } + + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(MemInitializerAST *ast) +{ + accept(ast->name); + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(MemberAccessAST *ast) +{ + out << spell(ast->access_token); + if (ast->template_token) { + out << "template"; + out << ' '; + } + accept(ast->member_name); + return false; +} + +bool PrettyPrinter::visit(NamedTypeSpecifierAST *ast) +{ + accept(ast->name); + return false; +} + +bool PrettyPrinter::visit(NamespaceAST *ast) +{ + out << "namespace"; + if (ast->identifier_token) { + out << ' '; + out << spell(ast->identifier_token); + } + for (SpecifierAST *it = ast->attributes; it; it = it->next) { + out << ' '; + accept(it); + } + out << ' '; + accept(ast->linkage_body); + return false; +} + +bool PrettyPrinter::visit(NamespaceAliasDefinitionAST *ast) +{ + out << "namespace"; + out << ' '; + out << spell(ast->namespace_name); + out << ' '; + out << '='; + out << ' '; + accept(ast->name); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(NestedDeclaratorAST *ast) +{ + out << '('; + accept(ast->declarator); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(NestedExpressionAST *ast) +{ + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(NestedNameSpecifierAST *ast) +{ + accept(ast->class_or_namespace_name); + if (ast->scope_token) + out << "::"; + return false; +} + +bool PrettyPrinter::visit(NewDeclaratorAST *ast) +{ + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) + accept(ast->declarator); + return false; +} + +bool PrettyPrinter::visit(NewExpressionAST *ast) +{ + if (ast->scope_token) + out << "::"; + out << "new"; + out << ' '; + if (ast->expression) { + accept(ast->expression); + if (ast->type_id) + out << ' '; + } + if (ast->type_id) { + accept(ast->type_id); + if (ast->new_type_id) + out << ' '; + } + if (ast->new_type_id) { + accept(ast->new_type_id); + if (ast->new_initializer) + out << ' '; + } + accept(ast->new_initializer); + return false; +} + +bool PrettyPrinter::visit(NewInitializerAST *ast) +{ + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(NewTypeIdAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->type_specifier) + out << ' '; + if (ast->new_initializer) { + accept(ast->new_initializer); + if (ast->new_declarator) + out << ' '; + } + accept(ast->new_declarator); + return false; +} + +bool PrettyPrinter::visit(NumericLiteralAST *ast) +{ + out << spell(ast->token); + return false; +} + +bool PrettyPrinter::visit(OperatorAST *ast) +{ + out << spell(ast->op_token); + if (ast->open_token) { + out << spell(ast->open_token); + out << spell(ast->close_token); + } + return false; +} + +bool PrettyPrinter::visit(OperatorFunctionIdAST *ast) +{ + out << "operator"; + out << ' '; + accept(ast->op); + return false; +} + +bool PrettyPrinter::visit(ParameterDeclarationAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarator) { + out << ' '; + accept(ast->declarator); + } + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + } + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(ParameterDeclarationClauseAST *ast) +{ + for (DeclarationAST *it = ast->parameter_declarations; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(PointerAST *ast) +{ + out << '*'; + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + return false; +} + +bool PrettyPrinter::visit(PointerToMemberAST *ast) +{ + if (ast->global_scope_token) + out << "::"; + for (NestedNameSpecifierAST *it = ast->nested_name_specifier; it; it = it->next) { + accept(it); + } + out << '*'; + for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + return false; +} + +bool PrettyPrinter::visit(PostIncrDecrAST *ast) +{ + out << spell(ast->incr_decr_token); + return false; +} + +bool PrettyPrinter::visit(PostfixExpressionAST *ast) +{ + accept(ast->base_expression); + for (PostfixAST *it = ast->postfix_expressions; it; it = it->next) { + accept(it); + } + return false; +} + +bool PrettyPrinter::visit(QualifiedNameAST *ast) +{ + if (ast->global_scope_token) + out << "::"; + for (NestedNameSpecifierAST *it = ast->nested_name_specifier; it; it = it->next) { + accept(it); + } + accept(ast->unqualified_name); + return false; +} + +bool PrettyPrinter::visit(ReferenceAST *) +{ + out << '&'; + return false; +} + +bool PrettyPrinter::visit(ReturnStatementAST *ast) +{ + out << "return"; + if (ast->expression) { + out << ' '; + accept(ast->expression); + } + out << ';'; + return false; +} + +bool PrettyPrinter::visit(SimpleDeclarationAST *ast) +{ + for (SpecifierAST *it = ast->decl_specifier_seq; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->declarators) { + if (ast->decl_specifier_seq) + out << ' '; + + for (DeclaratorListAST *it = ast->declarators; it; it = it->next) { + accept(it->declarator); + if (it->next) + out << ", "; + } + } + out << ';'; + return false; +} + +bool PrettyPrinter::visit(SimpleNameAST *ast) +{ + out << spell(ast->identifier_token); + return false; +} + +bool PrettyPrinter::visit(SimpleSpecifierAST *ast) +{ + out << spell(ast->specifier_token); + return false; +} + +bool PrettyPrinter::visit(SizeofExpressionAST *ast) +{ + out << "sizeof"; + out << ' '; + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(StringLiteralAST *ast) +{ + out << '"' << spell(ast->token) << '"'; + if (ast->next) { + out << ' '; + accept(ast->next); + } + return false; +} + +bool PrettyPrinter::visit(SwitchStatementAST *ast) +{ + out << "switch"; + out << ' '; + out << '('; + accept(ast->condition); + out << ')'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(TemplateArgumentListAST *ast) +{ + for (TemplateArgumentListAST *it = ast; it; it = it->next) { + accept(it->template_argument); + if (it->next) + out << ", "; + } + return false; +} + +bool PrettyPrinter::visit(TemplateDeclarationAST *ast) +{ + if (ast->export_token) { + out << "export"; + out << ' '; + } + out << "template"; + out << ' '; + out << '<'; + if (ast->template_parameters) { + out << ' '; + for (DeclarationAST *it = ast->template_parameters; it; it = it->next) { + accept(it); + if (it->next) + out << ", "; + } + out << ' '; + } + out << '>'; + newline(); + accept(ast->declaration); + return false; +} + +bool PrettyPrinter::visit(TemplateIdAST *ast) +{ + out << spell(ast->identifier_token); + out << '<'; + if (ast->template_arguments) { + out << ' '; + for (TemplateArgumentListAST *it = ast->template_arguments; it; it = it->next) { + accept(it->template_argument); + if (it->next) + out << ", "; + } + out << ' '; + } + out << '>'; + return false; +} + +bool PrettyPrinter::visit(TemplateTypeParameterAST *ast) +{ + out << "template"; + out << ' '; + out << '<'; + if (ast->template_parameters) { + out << ' '; + for (DeclarationAST *it = ast->template_parameters; it; it = it->next) { + accept(it); + if (it->next) + out << ",. "; + } + out << ' '; + } + out << '>'; + out << ' '; + out << "class"; + out << ' '; + accept(ast->name); + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + accept(ast->type_id); + } + return false; +} + +bool PrettyPrinter::visit(ThisExpressionAST *) +{ + out << "this"; + return false; +} + +bool PrettyPrinter::visit(ThrowExpressionAST *ast) +{ + out << "throw"; + out << ' '; + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(TranslationUnitAST *ast) +{ + for (DeclarationAST *it = ast->declarations; it; it = it->next) { + accept(it); + if (it->next) + newline(); + } + return false; +} + +bool PrettyPrinter::visit(TryBlockStatementAST *ast) +{ + out << "try"; + out << ' '; + accept(ast->statement); + for (CatchClauseAST *it = ast->catch_clause_seq; it; it = it->next) { + accept(it); + } + return false; +} + +bool PrettyPrinter::visit(TypeConstructorCallAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypeIdAST *ast) +{ + for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + accept(it); + if (it->next) + out << ' '; + } + if (ast->type_specifier && ast->declarator) { + out << ' '; + accept(ast->declarator); + } + return false; +} + +bool PrettyPrinter::visit(TypeidExpressionAST *ast) +{ + out << "typeid"; + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypeofSpecifierAST *ast) +{ + out << "typeof"; + out << '('; + accept(ast->expression); + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypenameCallExpressionAST *ast) +{ + out << "typename"; + out << ' '; + accept(ast->name); + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + +bool PrettyPrinter::visit(TypenameTypeParameterAST *ast) +{ + out << spell(ast->classkey_token); + if (ast->name) { + out << ' '; + accept(ast->name); + } + if (ast->equal_token) { + out << ' '; + out << '='; + out << ' '; + accept(ast->type_id); + } + return false; +} + +bool PrettyPrinter::visit(UnaryExpressionAST *ast) +{ + out << spell(ast->unary_op_token); + accept(ast->expression); + return false; +} + +bool PrettyPrinter::visit(UsingAST *ast) +{ + out << "using"; + out << ' '; + if (ast->typename_token) { + out << "typename"; + out << ' '; + } + accept(ast->name); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(UsingDirectiveAST *ast) +{ + out << "using"; + out << ' '; + out << "namespace"; + out << ' '; + accept(ast->name); + out << ';'; + return false; +} + +bool PrettyPrinter::visit(WhileStatementAST *ast) +{ + out << "while"; + out << ' '; + out << '('; + accept(ast->condition); + out << ')'; + accept(ast->statement); + return false; +} + +bool PrettyPrinter::visit(QtMethodAST *ast) +{ + out << ast->method_token; + out << '('; + accept(ast->declarator); + out << ')'; + return false; +} diff --git a/shared/cplusplus/PrettyPrinter.h b/shared/cplusplus/PrettyPrinter.h new file mode 100644 index 00000000000..966ebacd0e6 --- /dev/null +++ b/shared/cplusplus/PrettyPrinter.h @@ -0,0 +1,162 @@ +/*************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** +** Non-Open Source Usage +** +** Licensees may use this file in accordance with the Qt Beta Version +** License Agreement, Agreement version 2.2 provided with the Software or, +** alternatively, in accordance with the terms contained in a written +** agreement between you and Nokia. +** +** GNU General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU General +** Public License versions 2.0 or 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the packaging +** of this file. Please review the following information to ensure GNU +** General Public Licensing requirements will be met: +** +** http://www.fsf.org/licensing/licenses/info/GPLv2.html and +** http://www.gnu.org/copyleft/gpl.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt GPL Exception +** version 1.3, included in the file GPL_EXCEPTION.txt in this package. +** +***************************************************************************/ + +#ifndef CPLUSPLUS_PRETTYPRINTER_H +#define CPLUSPLUS_PRETTYPRINTER_H + +#include "CPlusPlusForwardDeclarations.h" +#include "ASTVisitor.h" + +#include + +CPLUSPLUS_BEGIN_HEADER +CPLUSPLUS_BEGIN_NAMESPACE + +class PrettyPrinter: protected ASTVisitor +{ +public: + PrettyPrinter(Control *control, std::ostream &out); + + void operator()(AST *ast); + +protected: + virtual bool visit(AccessDeclarationAST *ast); + virtual bool visit(ArrayAccessAST *ast); + virtual bool visit(ArrayDeclaratorAST *ast); + virtual bool visit(ArrayInitializerAST *ast); + virtual bool visit(AsmDefinitionAST *ast); + virtual bool visit(AttributeSpecifierAST *ast); + virtual bool visit(AttributeAST *ast); + virtual bool visit(BaseSpecifierAST *ast); + virtual bool visit(BinaryExpressionAST *ast); + virtual bool visit(BoolLiteralAST *ast); + virtual bool visit(BreakStatementAST *ast); + virtual bool visit(CallAST *ast); + virtual bool visit(CaseStatementAST *ast); + virtual bool visit(CastExpressionAST *ast); + virtual bool visit(CatchClauseAST *ast); + virtual bool visit(ClassSpecifierAST *ast); + virtual bool visit(CompoundStatementAST *ast); + virtual bool visit(ConditionAST *ast); + virtual bool visit(ConditionalExpressionAST *ast); + virtual bool visit(ContinueStatementAST *ast); + virtual bool visit(ConversionFunctionIdAST *ast); + virtual bool visit(CppCastExpressionAST *ast); + virtual bool visit(CtorInitializerAST *ast); + virtual bool visit(DeclaratorAST *ast); + virtual bool visit(DeclarationStatementAST *ast); + virtual bool visit(DeclaratorIdAST *ast); + virtual bool visit(DeclaratorListAST *ast); + virtual bool visit(DeleteExpressionAST *ast); + virtual bool visit(DestructorNameAST *ast); + virtual bool visit(DoStatementAST *ast); + virtual bool visit(ElaboratedTypeSpecifierAST *ast); + virtual bool visit(EmptyDeclarationAST *ast); + virtual bool visit(EnumSpecifierAST *ast); + virtual bool visit(EnumeratorAST *ast); + virtual bool visit(ExceptionDeclarationAST *ast); + virtual bool visit(ExceptionSpecificationAST *ast); + virtual bool visit(ExpressionListAST *ast); + virtual bool visit(ExpressionOrDeclarationStatementAST *ast); + virtual bool visit(ExpressionStatementAST *ast); + virtual bool visit(ForStatementAST *ast); + virtual bool visit(FunctionDeclaratorAST *ast); + virtual bool visit(FunctionDefinitionAST *ast); + virtual bool visit(GotoStatementAST *ast); + virtual bool visit(IfStatementAST *ast); + virtual bool visit(LabeledStatementAST *ast); + virtual bool visit(LinkageBodyAST *ast); + virtual bool visit(LinkageSpecificationAST *ast); + virtual bool visit(MemInitializerAST *ast); + virtual bool visit(MemberAccessAST *ast); + virtual bool visit(NamedTypeSpecifierAST *ast); + virtual bool visit(NamespaceAST *ast); + virtual bool visit(NamespaceAliasDefinitionAST *ast); + virtual bool visit(NestedDeclaratorAST *ast); + virtual bool visit(NestedExpressionAST *ast); + virtual bool visit(NestedNameSpecifierAST *ast); + virtual bool visit(NewDeclaratorAST *ast); + virtual bool visit(NewExpressionAST *ast); + virtual bool visit(NewInitializerAST *ast); + virtual bool visit(NewTypeIdAST *ast); + virtual bool visit(NumericLiteralAST *ast); + virtual bool visit(OperatorAST *ast); + virtual bool visit(OperatorFunctionIdAST *ast); + virtual bool visit(ParameterDeclarationAST *ast); + virtual bool visit(ParameterDeclarationClauseAST *ast); + virtual bool visit(PointerAST *ast); + virtual bool visit(PointerToMemberAST *ast); + virtual bool visit(PostIncrDecrAST *ast); + virtual bool visit(PostfixExpressionAST *ast); + virtual bool visit(QualifiedNameAST *ast); + virtual bool visit(ReferenceAST *ast); + virtual bool visit(ReturnStatementAST *ast); + virtual bool visit(SimpleDeclarationAST *ast); + virtual bool visit(SimpleNameAST *ast); + virtual bool visit(SimpleSpecifierAST *ast); + virtual bool visit(SizeofExpressionAST *ast); + virtual bool visit(StringLiteralAST *ast); + virtual bool visit(SwitchStatementAST *ast); + virtual bool visit(TemplateArgumentListAST *ast); + virtual bool visit(TemplateDeclarationAST *ast); + virtual bool visit(TemplateIdAST *ast); + virtual bool visit(TemplateTypeParameterAST *ast); + virtual bool visit(ThisExpressionAST *ast); + virtual bool visit(ThrowExpressionAST *ast); + virtual bool visit(TranslationUnitAST *ast); + virtual bool visit(TryBlockStatementAST *ast); + virtual bool visit(TypeConstructorCallAST *ast); + virtual bool visit(TypeIdAST *ast); + virtual bool visit(TypeidExpressionAST *ast); + virtual bool visit(TypeofSpecifierAST *ast); + virtual bool visit(TypenameCallExpressionAST *ast); + virtual bool visit(TypenameTypeParameterAST *ast); + virtual bool visit(UnaryExpressionAST *ast); + virtual bool visit(UsingAST *ast); + virtual bool visit(UsingDirectiveAST *ast); + virtual bool visit(WhileStatementAST *ast); + virtual bool visit(QtMethodAST *ast); + + void indent(); + void deindent(); + void newline(); + +private: + std::ostream &out; + unsigned depth; +}; + +CPLUSPLUS_END_NAMESPACE +CPLUSPLUS_END_HEADER + +#endif // CPLUSPLUS_PRETTYPRINTER_H diff --git a/shared/cplusplus/cplusplus.pri b/shared/cplusplus/cplusplus.pri index 2b3bb6804d2..c3042948c14 100644 --- a/shared/cplusplus/cplusplus.pri +++ b/shared/cplusplus/cplusplus.pri @@ -35,7 +35,9 @@ HEADERS += \ $$PWD/Token.h \ $$PWD/TranslationUnit.h \ $$PWD/Type.h \ - $$PWD/TypeVisitor.h + $$PWD/TypeVisitor.h \ + $$PWD/PrettyPrinter.h + SOURCES += \ $$PWD/AST.cpp \ @@ -69,5 +71,6 @@ SOURCES += \ $$PWD/Token.cpp \ $$PWD/TranslationUnit.cpp \ $$PWD/Type.cpp \ - $$PWD/TypeVisitor.cpp + $$PWD/TypeVisitor.cpp \ + $$PWD/PrettyPrinter.cpp From 80faa8ea7eae270d15600b337d906fdd3feccc1e Mon Sep 17 00:00:00 2001 From: lunowi Date: Sun, 4 Jan 2009 19:12:57 +0100 Subject: [PATCH 113/230] compile error on windows --- shared/cplusplus/PrettyPrinter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index 1cf8aad143f..ab086cb74c0 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -35,6 +35,7 @@ #include "AST.h" #include #include +#include CPLUSPLUS_USE_NAMESPACE From dfb837321101b924690b4b1588365eaa7930418a Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:18:16 +0100 Subject: [PATCH 114/230] Implemented ForStatementAST::lastToken(). --- shared/cplusplus/AST.cpp | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 0926323ed05..ccf41ea9ed3 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1362,7 +1362,6 @@ unsigned ExpressionListAST::firstToken() const unsigned ExpressionListAST::lastToken() const { - assert(0 && "review me"); for (const ExpressionListAST *it = this; it; it = it->next) { if (! it->next) return it->expression->lastToken(); @@ -1380,13 +1379,12 @@ void ExpressionOrDeclarationStatementAST::accept0(ASTVisitor *visitor) unsigned ExpressionOrDeclarationStatementAST::firstToken() const { - return expression->firstToken(); + return declaration->firstToken(); } unsigned ExpressionOrDeclarationStatementAST::lastToken() const { - assert(0 && "review me"); - return expression->lastToken(); + return declaration->lastToken(); } void ExpressionStatementAST::accept0(ASTVisitor *visitor) @@ -1405,8 +1403,12 @@ unsigned ExpressionStatementAST::firstToken() const unsigned ExpressionStatementAST::lastToken() const { - assert(0 && "review me"); - return expression->lastToken(); + if (semicolon_token) + return semicolon_token + 1; + else if (expression) + return expression->lastToken(); + // ### assert? + return 0; } void ForStatementAST::accept0(ASTVisitor *visitor) @@ -1426,10 +1428,22 @@ unsigned ForStatementAST::firstToken() const unsigned ForStatementAST::lastToken() const { - assert(0 && "review me"); if (statement) return statement->lastToken(); - return rparen_token + 1; + else if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (semicolon_token) + return semicolon_token + 1; + else if (condition) + return condition->lastToken(); + else if (initializer) + return initializer->lastToken(); + else if (lparen_token) + return lparen_token + 1; + + return for_token + 1; } void FunctionDeclaratorAST::accept0(ASTVisitor *visitor) From fb96595a658d2a3ef5e2bff89e151e6fad4cf10f Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:20:58 +0100 Subject: [PATCH 115/230] Implemented FunctionDeclaratorAST::lastToken(). --- shared/cplusplus/AST.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index ccf41ea9ed3..1bfe31676c4 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1459,16 +1459,20 @@ unsigned FunctionDeclaratorAST::firstToken() const unsigned FunctionDeclaratorAST::lastToken() const { - assert(0 && "review me"); if (exception_specification) return exception_specification->lastToken(); - else if (cv_qualifier_seq) { - for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { - if (! it->next) - return it->lastToken(); - } + + for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); } - return rparen_token + 1; + + if (rparen_token) + return rparen_token + 1; + else if (parameters) + return parameters->lastToken(); + + return lparen_token + 1; } void FunctionDefinitionAST::accept0(ASTVisitor *visitor) From 95c199309059930acd198cf0bd635b237a6b36d2 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:22:58 +0100 Subject: [PATCH 116/230] Implemented FunctionDefinitionAST::lastToken(). --- shared/cplusplus/AST.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 1bfe31676c4..2841d003a37 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1500,12 +1500,20 @@ unsigned FunctionDefinitionAST::firstToken() const unsigned FunctionDefinitionAST::lastToken() const { - assert(0 && "review me"); if (function_body) return function_body->lastToken(); else if (ctor_initializer) return ctor_initializer->lastToken(); - return declarator->lastToken(); + if (declarator) + return declarator->lastToken(); + + for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + // ### assert + return 0; } void GotoStatementAST::accept0(ASTVisitor *visitor) From 2fdbfe87efc26cc7927d39d59e63983cb0c01b93 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:24:09 +0100 Subject: [PATCH 117/230] Implemented GotoStatementAST::lastToken(). --- shared/cplusplus/AST.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 2841d003a37..67ff46ca4fe 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1529,8 +1529,13 @@ unsigned GotoStatementAST::firstToken() const unsigned GotoStatementAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + else if (identifier_token) + return identifier_token + 1; + else if (goto_token) + return goto_token + 1; + return 0; } void IfStatementAST::accept0(ASTVisitor *visitor) From 5e40f21183178a5ae4023b91d6266bb0bea0ac97 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:26:20 +0100 Subject: [PATCH 118/230] Implemented IfStatementAST::lastToken(). --- shared/cplusplus/AST.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 67ff46ca4fe..33de30e968f 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1554,14 +1554,19 @@ unsigned IfStatementAST::firstToken() const unsigned IfStatementAST::lastToken() const { - assert(0 && "review me"); if (else_statement) return else_statement->lastToken(); else if (else_token) return else_token + 1; else if (statement) return statement->lastToken(); - return rparen_token + 1; + else if (rparen_token) + return rparen_token + 1; + else if (condition) + return condition->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return if_token + 1; } void LabeledStatementAST::accept0(ASTVisitor *visitor) From 77c16d13172cad7a801a30ab53953dee04418f01 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:27:49 +0100 Subject: [PATCH 119/230] Implemented LabeledStatementAST::lastToken(). --- shared/cplusplus/AST.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 33de30e968f..f75fcf12a41 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1583,10 +1583,11 @@ unsigned LabeledStatementAST::firstToken() const unsigned LabeledStatementAST::lastToken() const { - assert(0 && "review me"); if (statement) return statement->lastToken(); - return colon_token + 1; + else if (colon_token) + return colon_token + 1; + return label_token + 1; } void LinkageBodyAST::accept0(ASTVisitor *visitor) From 4fcadbdd49879c43c77d25faab833422bb82dd3a Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:29:12 +0100 Subject: [PATCH 120/230] Implemented LinkageBodyAST::lastToken(). --- shared/cplusplus/AST.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index f75fcf12a41..90cd140ef8f 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1606,8 +1606,15 @@ unsigned LinkageBodyAST::firstToken() const unsigned LinkageBodyAST::lastToken() const { - assert(0 && "review me"); - return rbrace_token + 1; + if (rbrace_token) + return rbrace_token + 1; + + for (DeclarationAST *it = declarations; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return lbrace_token + 1; } void LinkageSpecificationAST::accept0(ASTVisitor *visitor) From 1dbdea5fcc3973ebd4f10c7a9cdb84855ee6c57f Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:31:15 +0100 Subject: [PATCH 121/230] Implemented MemInitializerAST::lastToken(). --- shared/cplusplus/AST.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 90cd140ef8f..f894a16167a 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1631,7 +1631,6 @@ unsigned LinkageSpecificationAST::firstToken() const unsigned LinkageSpecificationAST::lastToken() const { - assert(0 && "review me"); if (declaration) return declaration->lastToken(); else if (extern_type) @@ -1653,8 +1652,13 @@ unsigned MemInitializerAST::firstToken() const unsigned MemInitializerAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return name->lastToken(); } void MemberAccessAST::accept0(ASTVisitor *visitor) From cc8382189062153e45db3fd6729fdc8e2e211c4e Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:32:28 +0100 Subject: [PATCH 122/230] Implemented MemberAccessAST::lastToken(). --- shared/cplusplus/AST.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index f894a16167a..911ba399ed8 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1675,9 +1675,10 @@ unsigned MemberAccessAST::firstToken() const unsigned MemberAccessAST::lastToken() const { - assert(0 && "review me"); if (member_name) return member_name->lastToken(); + else if (template_token) + return template_token + 1; return access_token + 1; } From fdd77d8c7dab2576d368c06a0c8f7c66f15e2bb6 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:34:06 +0100 Subject: [PATCH 123/230] Implemented NamespaceAST::lastToken(). --- shared/cplusplus/AST.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 911ba399ed8..761e1bd535d 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1696,7 +1696,6 @@ unsigned NamedTypeSpecifierAST::firstToken() const unsigned NamedTypeSpecifierAST::lastToken() const { - assert(0 && "review me"); return name->lastToken(); } @@ -1717,11 +1716,17 @@ unsigned NamespaceAST::firstToken() const unsigned NamespaceAST::lastToken() const { - assert(0 && "review me"); if (linkage_body) return linkage_body->lastToken(); + + for (SpecifierAST *it = attributes; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + if (identifier_token) return identifier_token + 1; + return namespace_token + 1; } From ae49c6b4874e07fda31aea4856cee576fc03e7e2 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:40:11 +0100 Subject: [PATCH 124/230] Implemented NamespaceAliasDefinitionAST::lastToken(). --- shared/cplusplus/AST.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 761e1bd535d..7165bacbcf9 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1744,8 +1744,15 @@ unsigned NamespaceAliasDefinitionAST::firstToken() const unsigned NamespaceAliasDefinitionAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + else if (name) + return name->lastToken(); + else if (equal_token) + return equal_token + 1; + else if (namespace_name) + return namespace_name + 1; + return namespace_token + 1; } void NestedDeclaratorAST::accept0(ASTVisitor *visitor) From bf554cb45c38bf724480efb14bb40b60112fb379 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 10:41:26 +0100 Subject: [PATCH 125/230] Implemented NestedDeclaratorAST::lastToken(). --- shared/cplusplus/AST.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 7165bacbcf9..5ddfe4774c3 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1769,8 +1769,11 @@ unsigned NestedDeclaratorAST::firstToken() const unsigned NestedDeclaratorAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + else if (declarator) + return declarator->lastToken(); + return lparen_token + 1; } void NestedExpressionAST::accept0(ASTVisitor *visitor) From 2ec448d1d731b24db82a1f5e02d43754782fbebe Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Fri, 2 Jan 2009 09:33:47 +0100 Subject: [PATCH 126/230] Fixes: Fix a styling issue with toolbuttons Details: This ensures that the manhattan button arrow does not depend on the menubutton indicator size, which it should not. --- src/plugins/coreplugin/manhattanstyle.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreplugin/manhattanstyle.cpp b/src/plugins/coreplugin/manhattanstyle.cpp index 4f41be3fc81..ecc0683d283 100644 --- a/src/plugins/coreplugin/manhattanstyle.cpp +++ b/src/plugins/coreplugin/manhattanstyle.cpp @@ -894,11 +894,12 @@ void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOpti tool.rect = tool.rect.adjusted(2, 2, -2, -2); drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget); } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { - int mbi = pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); + int arrowSize = 6; QRect ir = toolbutton->rect.adjusted(1, 1, -1, -1); QStyleOptionToolButton newBtn = *toolbutton; newBtn.palette = panelPalette(option->palette); - newBtn.rect = QRect(ir.right() + 5 - mbi, ir.height() - mbi + 4, mbi - 6, mbi - 6); + newBtn.rect = QRect(ir.right() - arrowSize - 1, + ir.height() - arrowSize - 2, arrowSize, arrowSize); QWindowsStyle::drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget); } } From 17722a6c796319dc1cf9b757792aad55a39f4738 Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Mon, 5 Jan 2009 10:42:42 +0100 Subject: [PATCH 127/230] Fixes: Fix hover on toolbuttons RevBy: trust me Details: Now that hover is correctly implemented for toolbuttons, we actually have to check the sunken state. --- src/plugins/coreplugin/manhattanstyle.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/coreplugin/manhattanstyle.cpp b/src/plugins/coreplugin/manhattanstyle.cpp index ecc0683d283..5b72c891cd6 100644 --- a/src/plugins/coreplugin/manhattanstyle.cpp +++ b/src/plugins/coreplugin/manhattanstyle.cpp @@ -822,10 +822,12 @@ void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOpti } State mflags = bflags; - if (toolbutton->activeSubControls & SC_ToolButton) - bflags |= State_Sunken; - if (toolbutton->activeSubControls & SC_ToolButtonMenu) - mflags |= State_Sunken; + if (toolbutton->state & State_Sunken) { + if (toolbutton->activeSubControls & SC_ToolButton) + bflags |= State_Sunken; + if (toolbutton->activeSubControls & SC_ToolButtonMenu) + mflags |= State_Sunken; + } QStyleOption tool(0); tool.palette = toolbutton->palette; From b904780f0eb949d3ac6153935a9d4155097456f8 Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Mon, 5 Jan 2009 11:58:38 +0100 Subject: [PATCH 128/230] Fixes: Fix painting of tabrect with -reverse Details: Still not perfect due to inverted gradients, but much better. --- src/plugins/coreplugin/fancytabwidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/coreplugin/fancytabwidget.cpp b/src/plugins/coreplugin/fancytabwidget.cpp index c24e551c77e..ccf9c92322c 100644 --- a/src/plugins/coreplugin/fancytabwidget.cpp +++ b/src/plugins/coreplugin/fancytabwidget.cpp @@ -323,6 +323,7 @@ void FancyTabWidget::paintEvent(QPaintEvent *event) QPainter p(this); QRect rect = m_selectionWidget->rect().adjusted(0, 0, 1, 0); + rect = style()->visualRect(layoutDirection(), geometry(), rect); StyleHelper::verticalGradient(&p, rect, rect); p.setPen(StyleHelper::borderColor()); p.drawLine(rect.topRight(), rect.bottomRight()); From c0344c6daca7684d05b39f2ceca92190236f3af9 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 5 Jan 2009 12:21:32 +0100 Subject: [PATCH 129/230] Fixes: make "Hello World" plugin compilabe RevBy: con make "Hello World" plugin compilabe --- src/plugins/helloworld/helloworldplugin.cpp | 45 ++++++++------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/src/plugins/helloworld/helloworldplugin.cpp b/src/plugins/helloworld/helloworldplugin.cpp index 296c00454ee..a8eb79c0519 100644 --- a/src/plugins/helloworld/helloworldplugin.cpp +++ b/src/plugins/helloworld/helloworldplugin.cpp @@ -33,26 +33,21 @@ #include "helloworldplugin.h" -#include "helloworldwindow.h" - -#include #include -#include -#include +#include #include +#include +#include #include +#include #include -#include +#include #include #include #include #include -#include - -#include "helloworldplugin.h" - using namespace HelloWorld::Internal; /*! Constructs the Hello World plugin. Normally plugins don't do anything in @@ -77,30 +72,20 @@ HelloWorldPlugin::~HelloWorldPlugin() \a error_message can be used to pass an error message to the plugin system, if there was any. */ -bool HelloWorldPlugin::initialize(const QStringList & /*arguments*/, QString *error_message) +bool HelloWorldPlugin::initialize(const QStringList &arguments, QString *error_message) { + Q_UNUSED(arguments) Q_UNUSED(error_message) // Get the primary access point to the workbench. Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject(); - // Create our own widget that we want to show in a view in the IDE. - HelloWorldWindow *window = new HelloWorldWindow; - // Create a unique context id for our own view, that will be used for the // menu entry later. QList context = QList() << core->uniqueIDManager()->uniqueIdentifier( QLatin1String("HelloWorld.MainView")); - // Create a new view that contains our widget and register it with the - // plugin manager. The view will have the id "HelloWorld.HelloWorldWindow", - // and if it has focus it provides 'context' to the context list in - // Qt Creator. It will be put into the right dock widget area. - addAutoReleasedObject(new Core::BaseView("HelloWorld.HelloWorldWindow", - window, context, - Qt::RightDockWidgetArea)); - // Create an action to be triggered by a menu entry QAction *helloWorldAction = new QAction("Say \"&Hello World!\"", this); connect(helloWorldAction, SIGNAL(triggered()), SLOT(sayHelloWorld())); @@ -126,13 +111,15 @@ bool HelloWorldPlugin::initialize(const QStringList & /*arguments*/, QString *er actionManager->actionContainer(Core::Constants::M_TOOLS); toolsMenu->addMenu(helloWorldMenu); - // Add a mode with a push button based on BaseMode. Like the BaseView, it will unregister - // itself from the plugin manager when it is deleted. - addAutoReleasedObject(new Core::BaseMode(tr("Hello world!"), - "HelloWorld.HelloWorldMode", - QIcon(), - 0, // priority - new QPushButton(tr("Hello World PushButton!")))); + // Add a mode with a push button based on BaseMode. Like the BaseView, + // it will unregister itself from the plugin manager when it is deleted. + Core::BaseMode *baseMode = new Core::BaseMode; + baseMode->setUniqueModeName("HelloWorld.HelloWorldMode"); + baseMode->setName(tr("Hello world!")); + baseMode->setIcon(QIcon()); + baseMode->setPriority(0); + baseMode->setWidget(new QPushButton(tr("Hello World PushButton!"))); + addAutoReleasedObject(baseMode); // Add the Hello World action command to the mode manager (with 0 priority) Core::ModeManager *modeManager = core->modeManager(); From 808b5df55d05771697d84a9b0b3fb9e7ee0562bf Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 5 Jan 2009 12:54:52 +0100 Subject: [PATCH 130/230] Fixes: try __dlopen and dlopen to make systems like CentOS 4.6 happy Task: Message-ID: @qt-creator --- src/plugins/debugger/debuggerplugin.cpp | 2 +- src/plugins/debugger/gdbengine.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 0f50ea461a5..d65f9ac9acd 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -63,10 +63,10 @@ #include #include -#include #include #include #include +#include #include #include diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 002e643c136..5ba169f9293 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -3945,7 +3945,9 @@ void GdbEngine::tryLoadCustomDumpers() if (qq->useFastStart()) sendCommand("set stop-on-solib-events 0"); QString flag = QString::number(RTLD_NOW); - sendCommand("call dlopen(\"" + lib + "\", " + flag + ")"); + sendCommand("call (void)dlopen(\"" + lib + "\", " + flag + ")"); + // some older systems like CentOS 4.6 prefer this: + sendCommand("call (void)__dlopen(\"" + lib + "\", " + flag + ")"); sendCommand("sharedlibrary " + dotEscape(lib)); if (qq->useFastStart()) sendCommand("set stop-on-solib-events 1"); From 6848155c7d3b9eaa7dba31032b47c80c8f1abc71 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 5 Jan 2009 13:45:30 +0100 Subject: [PATCH 131/230] Fixes: Add "Apply" button to Preferences dialog RevBy: con --- .../coreplugin/dialogs/settingsdialog.cpp | 8 +++ .../coreplugin/dialogs/settingsdialog.h | 1 + .../coreplugin/dialogs/settingsdialog.ui | 71 +++++++++---------- 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp index b4a8c2b8ea6..e2865bf1830 100644 --- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp +++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp @@ -47,6 +47,8 @@ SettingsDialog::SettingsDialog(QWidget *parent, const QString &initialCategory, setupUi(this); buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); + connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply())); + splitter->setCollapsible(1, false); pageTree->header()->setVisible(false); @@ -135,3 +137,9 @@ void SettingsDialog::reject() page->finished(false); done(QDialog::Rejected); } + +void SettingsDialog::apply() +{ + foreach (IOptionsPage *page, m_pages) + page->finished(true); +} diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.h b/src/plugins/coreplugin/dialogs/settingsdialog.h index c277c852671..6dd8a2a37da 100644 --- a/src/plugins/coreplugin/dialogs/settingsdialog.h +++ b/src/plugins/coreplugin/dialogs/settingsdialog.h @@ -57,6 +57,7 @@ private slots: void pageSelected(QTreeWidgetItem *cat); void accept(); void reject(); + void apply(); private: QList m_pages; diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.ui b/src/plugins/coreplugin/dialogs/settingsdialog.ui index 9d2475536c0..aad114f848c 100644 --- a/src/plugins/coreplugin/dialogs/settingsdialog.ui +++ b/src/plugins/coreplugin/dialogs/settingsdialog.ui @@ -1,7 +1,8 @@ - + + SettingsDialog - - + + 0 0 @@ -9,50 +10,48 @@ 476 - + Options - - - 9 - - + + 6 + + 9 + - - + + Qt::Horizontal - - - - 7 - 7 + + + 0 0 - + 1 - + 0 - - - - 0 - - + + + 6 + + 0 + - - + + 350 250 @@ -61,8 +60,8 @@ - - + + Qt::Horizontal @@ -72,12 +71,12 @@ - - + + Qt::Horizontal - - QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -91,11 +90,11 @@ SettingsDialog accept() - + 297 361 - + 297 193 @@ -107,11 +106,11 @@ SettingsDialog reject() - + 297 361 - + 297 193 From d54e8d95d470a8c815e3638abe49e1a21d045e32 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 5 Jan 2009 13:56:31 +0100 Subject: [PATCH 132/230] Fixes: fix signature of FakeVimPlugin::removeHandler Details: QObject * -> QWidget * --- src/plugins/fakevim/fakevimplugin.cpp | 10 +++++----- src/plugins/fakevim/fakevimplugin.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 72671a37c60..20b3b082a58 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -165,14 +165,14 @@ void FakeVimPlugin::installHandler() //QMainWindow mw; connect(m_handler, SIGNAL(commandBufferChanged(QString)), this, SLOT(showCommandBuffer(QString))); - connect(m_handler, SIGNAL(quitRequested(QObject *)), - this, SLOT(removeHandler(QObject *))); + connect(m_handler, SIGNAL(quitRequested(QWidget *)), + this, SLOT(removeHandler(QWidget *))); } -void FakeVimPlugin::removeHandler(QObject *ob) +void FakeVimPlugin::removeHandler(QWidget *widget) { - ob->removeEventFilter(m_handler); - QPlainTextEdit *plainTextEdit = qobject_cast(ob); + widget->removeEventFilter(m_handler); + QPlainTextEdit *plainTextEdit = qobject_cast(widget); if (!plainTextEdit) return; plainTextEdit->setCursorWidth(m_savedCursorWidth); diff --git a/src/plugins/fakevim/fakevimplugin.h b/src/plugins/fakevim/fakevimplugin.h index f31ad1e68e6..6561e871b00 100644 --- a/src/plugins/fakevim/fakevimplugin.h +++ b/src/plugins/fakevim/fakevimplugin.h @@ -67,7 +67,7 @@ private: private slots: void installHandler(); - void removeHandler(QObject *ob); + void removeHandler(QWidget *widget); void showCommandBuffer(const QString &contents); private: From ce6bbe65f3e8550122e91305277649e0efa61881 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 14:07:57 +0100 Subject: [PATCH 133/230] Implemented NestedExpressionAST::lastToken() --- shared/cplusplus/AST.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 5ddfe4774c3..dcf32573616 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1790,8 +1790,11 @@ unsigned NestedExpressionAST::firstToken() const unsigned NestedExpressionAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + return lparen_token + 1; } void NestedNameSpecifierAST::accept0(ASTVisitor *visitor) @@ -1809,8 +1812,9 @@ unsigned NestedNameSpecifierAST::firstToken() const unsigned NestedNameSpecifierAST::lastToken() const { - assert(0 && "review me"); - return scope_token + 1; + if (scope_token) + return scope_token + 1; + return class_or_namespace_name->lastToken(); } void NewDeclaratorAST::accept0(ASTVisitor *visitor) From 75b761320378e1c453e65e7e1067bec35e464122 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 5 Jan 2009 14:13:09 +0100 Subject: [PATCH 134/230] Fixes: re-enable "Start External Application" in debug mode --- src/plugins/debugger/gdbengine.cpp | 2 +- tests/manual/gdbdebugger/simple/app.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 5ba169f9293..d7fc76f107c 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -1616,7 +1616,7 @@ bool GdbEngine::startDebugger() sendCommand("attach " + QString::number(q->m_attachedPID)); } - if (q->startMode() == q->startInternal) { + if (q->startMode() == q->startInternal || q->startMode() == q->startExternal) { sendCommand("-file-exec-and-symbols " + fileName, GdbFileExecAndSymbols); #ifdef Q_OS_MAC sendCommand("sharedlibrary apply-load-rules all"); diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 5156e6fb5fd..3243e9c70e2 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -868,7 +868,7 @@ int main(int argc, char *argv[]) testQVectorOfQList(); - *(int *)0 = 0; + //*(int *)0 = 0; testQObject(argc, argv); From 6705bc7e607156559157054189cdb0b4de57cb66 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 5 Jan 2009 14:38:51 +0100 Subject: [PATCH 135/230] Fixes: simplify "Attach to Running Process" code Details: also sorts by process name by default --- src/plugins/debugger/attachexternaldialog.cpp | 8 +++----- src/plugins/debugger/attachexternaldialog.h | 3 +-- src/plugins/debugger/debuggermanager.cpp | 3 +-- src/plugins/debugger/gdbengine.cpp | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/plugins/debugger/attachexternaldialog.cpp b/src/plugins/debugger/attachexternaldialog.cpp index c60130e6569..11e0265912b 100644 --- a/src/plugins/debugger/attachexternaldialog.cpp +++ b/src/plugins/debugger/attachexternaldialog.cpp @@ -49,12 +49,11 @@ using namespace Debugger::Internal; -AttachExternalDialog::AttachExternalDialog(QWidget *parent, const QString &pid) +AttachExternalDialog::AttachExternalDialog(QWidget *parent) : QDialog(parent) { setupUi(this); buttonBox->button(QDialogButtonBox::Ok)->setDefault(true); - m_defaultPID = pid; m_model = new QStandardItemModel(this); procView->setSortingEnabled(true); @@ -65,8 +64,6 @@ AttachExternalDialog::AttachExternalDialog(QWidget *parent, const QString &pid) connect(procView, SIGNAL(activated(const QModelIndex &)), this, SLOT(procSelected(const QModelIndex &))); - - pidLineEdit->setText(m_defaultPID); rebuildProcessList(); } @@ -91,7 +88,7 @@ static void insertItem(QStandardItem *root, const QString &pid, //qDebug() << "HANDLING " << pid; QStandardItem *parent = 0; const ProcData &proc = procs[pid]; - if (1 || pid == "0") { + if (1 || pid == "0") { // FIXME: a real tree is not-so-nice to search parent = root; } else { if (!known.contains(proc.ppid)) @@ -148,6 +145,7 @@ void AttachExternalDialog::rebuildProcessList() procView->expandAll(); procView->resizeColumnToContents(0); procView->resizeColumnToContents(1); + procView->sortByColumn(1, Qt::AscendingOrder); } #ifdef Q_OS_WINDOWS diff --git a/src/plugins/debugger/attachexternaldialog.h b/src/plugins/debugger/attachexternaldialog.h index 4970fa79258..d04d1bd61b5 100644 --- a/src/plugins/debugger/attachexternaldialog.h +++ b/src/plugins/debugger/attachexternaldialog.h @@ -48,7 +48,7 @@ class AttachExternalDialog : public QDialog, Ui::AttachExternalDialog Q_OBJECT public: - explicit AttachExternalDialog(QWidget *parent, const QString &pid); + explicit AttachExternalDialog(QWidget *parent); int attachPID() const; private slots: @@ -56,7 +56,6 @@ private slots: void procSelected(const QModelIndex &); private: - QString m_defaultPID; QStandardItemModel *m_model; }; diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 119868ab09c..2d6def04da4 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -804,8 +804,7 @@ bool DebuggerManager::startNewDebugger(StartMode mode) m_workingDir = QString(); m_attachedPID = -1; } else if (startMode() == attachExternal) { - QString pid; - AttachExternalDialog dlg(mainWindow(), pid); + AttachExternalDialog dlg(mainWindow()); if (dlg.exec() != QDialog::Accepted) return false; m_executable = QString(); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index d7fc76f107c..f25cb748707 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -2401,7 +2401,7 @@ void GdbEngine::handleStackListFrames(const GdbResultRecord &record) if (usable) q->gotoLocation(frame.file, frame.line, true); else - qDebug() << "FULL NAME NOT USABLE 0: " << frame.file; + qDebug() << "FULL NAME NOT USABLE 0: " << frame.file << topFrame; } #endif } From 7fbc2286000dcc62518664701c12310a3910a8b1 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 5 Jan 2009 14:56:59 +0100 Subject: [PATCH 136/230] Fixes: Fix starting external programs Details: Was broken due to duplicate but not synchronized internal pid data --- src/plugins/debugger/gdbengine.cpp | 8 ++++---- src/plugins/debugger/gdbengine.h | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index f25cb748707..7c7d3b6d328 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -650,7 +650,7 @@ void GdbEngine::interruptInferior() if (m_gdbProc.state() == QProcess::NotRunning) return; - if (q->m_attachedPID) { + if (q->m_attachedPID > 0) { if (interruptProcess(q->m_attachedPID)) qq->notifyInferiorStopped(); return; @@ -660,6 +660,7 @@ void GdbEngine::interruptInferior() sendCommand("-exec-interrupt", GdbExecInterrupt); qq->notifyInferiorStopped(); #else + qDebug() << "CANNOT STOP INFERIOR" << m_gdbProc.pid(); if (interruptChildProcess(m_gdbProc.pid())) qq->notifyInferiorStopped(); #endif @@ -672,9 +673,9 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0) qDebug() << "Cannot parse PID from " << pid0; return; } - if (pid == m_inferiorPid) + if (pid == q->m_attachedPID) return; - m_inferiorPid = pid; + q->m_attachedPID = pid; qq->notifyInferiorPidChanged(pid); } @@ -1514,7 +1515,6 @@ int GdbEngine::currentFrame() const bool GdbEngine::startDebugger() { - m_inferiorPid = 0; QStringList gdbArgs; QFileInfo fi(q->m_executable); diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h index 434a110a454..c1344f86dda 100644 --- a/src/plugins/debugger/gdbengine.h +++ b/src/plugins/debugger/gdbengine.h @@ -330,7 +330,6 @@ private: QString m_editedData; int m_pendingRequests; - int m_inferiorPid; QStringList m_availableSimpleDumpers; QString m_namespace; // namespace used in "namespaced Qt"; From 85babacb5acc26f28844be44b9275c1be33b144f Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 15:23:44 +0100 Subject: [PATCH 137/230] Replace a. with a[0]. when `a' has type array of T. --- src/plugins/cpptools/cppcodecompletion.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index 50e5432f2f8..b1184420bf6 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -662,6 +662,24 @@ bool CppCodeCompletion::completeMember(const QList &re ty = refTy->elementType(); NamedType *namedTy = 0; + + if (ArrayType *arrayTy = ty->asArrayType()) { + // Replace . with [0]. when `ty' is an array type. + FullySpecifiedType elementTy = arrayTy->elementType(); + + if (ReferenceType *refTy = elementTy->asReferenceType()) + elementTy = refTy->elementType(); + + if (elementTy->isNamedType() || elementTy->isPointerType()) { + ty = elementTy; + + const int length = m_editor->position() - m_startPosition + 1; + m_editor->setCurPos(m_startPosition - 1); + m_editor->replace(length, QLatin1String("[0].")); + m_startPosition += 3; + } + } + if (PointerType *ptrTy = ty->asPointerType()) { // Replace . with -> int length = m_editor->position() - m_startPosition + 1; From 8f5d55c3d8cd7ff8df2bdf4f12d168e48ea81e68 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 5 Jan 2009 15:55:37 +0100 Subject: [PATCH 138/230] remove dead code --- src/plugins/debugger/attachexternaldialog.cpp | 181 ----------------- src/plugins/debugger/attachremotedialog.cpp | 187 ------------------ 2 files changed, 368 deletions(-) diff --git a/src/plugins/debugger/attachexternaldialog.cpp b/src/plugins/debugger/attachexternaldialog.cpp index 11e0265912b..7ca50470fb5 100644 --- a/src/plugins/debugger/attachexternaldialog.cpp +++ b/src/plugins/debugger/attachexternaldialog.cpp @@ -148,187 +148,6 @@ void AttachExternalDialog::rebuildProcessList() procView->sortByColumn(1, Qt::AscendingOrder); } -#ifdef Q_OS_WINDOWS - -BOOL GetProcessList(); -BOOL ListProcessModules(DWORD dwPID); -BOOL ListProcessThreads(DWORD dwOwnerPID); -void printError(TCHAR *msg); - -BOOL GetProcessList() -{ - HANDLE hProcessSnap; - HANDLE hProcess; - PROCESSENTRY32 pe32; - DWORD dwPriorityClass; - - // Take a snapshot of all processes in the system. - hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); - if (hProcessSnap == INVALID_HANDLE_VALUE) - { - printError( TEXT("CreateToolhelp32Snapshot (of processes)") ); - return( FALSE ); - } - - // Set the size of the structure before using it. - pe32.dwSize = sizeof( PROCESSENTRY32 ); - - // Retrieve information about the first process, - // and exit if unsuccessful - if (!Process32First( hProcessSnap, &pe32 )) - { - printError( TEXT("Process32First") ); // show cause of failure - CloseHandle( hProcessSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the snapshot of processes, and - // display information about each process in turn - do - { - printf( "\n\n=====================================================" ); - _tprintf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile ); - printf( "\n-----------------------------------------------------" ); - - // Retrieve the priority class. - dwPriorityClass = 0; - hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID ); - if (hProcess == NULL) - printError( TEXT("OpenProcess") ); - else - { - dwPriorityClass = GetPriorityClass( hProcess ); - if (!dwPriorityClass) - printError( TEXT("GetPriorityClass") ); - CloseHandle( hProcess ); - } - - printf( "\n Process ID = 0x%08X", pe32.th32ProcessID ); - printf( "\n Thread count = %d", pe32.cntThreads ); - printf( "\n Parent process ID = 0x%08X", pe32.th32ParentProcessID ); - printf( "\n Priority base = %d", pe32.pcPriClassBase ); - if (dwPriorityClass) - printf( "\n Priority class = %d", dwPriorityClass ); - - // List the modules and threads associated with this process - ListProcessModules( pe32.th32ProcessID ); - ListProcessThreads( pe32.th32ProcessID ); - - } while (Process32Next(hProcessSnap, &pe32)); - - CloseHandle(hProcessSnap); - return TRUE; -} - - -BOOL ListProcessModules(DWORD dwPID) -{ - HANDLE hModuleSnap = INVALID_HANDLE_VALUE; - MODULEENTRY32 me32; - - // Take a snapshot of all modules in the specified process. - hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID ); - if (hModuleSnap == INVALID_HANDLE_VALUE) { - printError(TEXT("CreateToolhelp32Snapshot (of modules)")); - return FALSE; - } - - // Set the size of the structure before using it. - me32.dwSize = sizeof( MODULEENTRY32 ); - - // Retrieve information about the first module, - // and exit if unsuccessful - if (!Module32First( hModuleSnap, &me32)) - { - printError( TEXT("Module32First") ); // show cause of failure - CloseHandle( hModuleSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the module list of the process, - // and display information about each module - do - { - _tprintf( TEXT("\n\n MODULE NAME: %s"), me32.szModule ); - _tprintf( TEXT("\n Executable = %s"), me32.szExePath ); - printf( "\n Process ID = 0x%08X", me32.th32ProcessID ); - printf( "\n Ref count (g) = 0x%04X", me32.GlblcntUsage ); - printf( "\n Ref count (p) = 0x%04X", me32.ProccntUsage ); - printf( "\n Base address = 0x%08X", (DWORD) me32.modBaseAddr ); - printf( "\n Base size = %d", me32.modBaseSize ); - - } while (Module32Next(hModuleSnap, &me32)); - - CloseHandle(hModuleSnap); - return TRUE; -} - -BOOL ListProcessThreads( DWORD dwOwnerPID ) -{ - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); - if (hThreadSnap == INVALID_HANDLE_VALUE) - return( FALSE ); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32 ); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if (!Thread32First( hThreadSnap, &te32 )) - { - printError( TEXT("Thread32First") ); // show cause of failure - CloseHandle( hThreadSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if (te32.th32OwnerProcessID == dwOwnerPID) - { - printf( "\n\n THREAD ID = 0x%08X", te32.th32ThreadID ); - printf( "\n Base priority = %d", te32.tpBasePri ); - printf( "\n Delta priority = %d", te32.tpDeltaPri ); - } - } while (Thread32Next(hThreadSnap, &te32)); - - CloseHandle( hThreadSnap ); - return( TRUE ); -} - -void printError( TCHAR* msg ) -{ - DWORD eNum; - TCHAR sysMsg[256]; - TCHAR* p; - - eNum = GetLastError( ); - FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, eNum, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - sysMsg, 256, NULL ); - - // Trim the end of the line and terminate it with a null - p = sysMsg; - while (*p > 31 || *p == 9 ) - ++p; - - do { - *p-- = 0; - } while( p >= sysMsg && (*p == '.' || *p < 33)); - - // Display the message - _tprintf( TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg ); -} - -#endif - void AttachExternalDialog::procSelected(const QModelIndex &index0) { QModelIndex index = index0.sibling(index0.row(), 0); diff --git a/src/plugins/debugger/attachremotedialog.cpp b/src/plugins/debugger/attachremotedialog.cpp index ffe21174239..e13d7b6ebc2 100644 --- a/src/plugins/debugger/attachremotedialog.cpp +++ b/src/plugins/debugger/attachremotedialog.cpp @@ -142,193 +142,6 @@ void AttachRemoteDialog::rebuildProcessList() procView->resizeColumnToContents(1); } -#ifdef Q_OS_WINDOWS - -#include -#include -#include -#include - -// Forward declarations: -BOOL GetProcessList(); -BOOL ListProcessModules(DWORD dwPID); -BOOL ListProcessThreads(DWORD dwOwnerPID); -void printError(TCHAR* msg); - -BOOL GetProcessList( ) -{ - HANDLE hProcessSnap; - HANDLE hProcess; - PROCESSENTRY32 pe32; - DWORD dwPriorityClass; - - // Take a snapshot of all processes in the system. - hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); - if (hProcessSnap == INVALID_HANDLE_VALUE) - { - printError( TEXT("CreateToolhelp32Snapshot (of processes)") ); - return( FALSE ); - } - - // Set the size of the structure before using it. - pe32.dwSize = sizeof( PROCESSENTRY32 ); - - // Retrieve information about the first process, - // and exit if unsuccessful - if (!Process32First( hProcessSnap, &pe32 )) - { - printError( TEXT("Process32First") ); // show cause of failure - CloseHandle( hProcessSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the snapshot of processes, and - // display information about each process in turn - do - { - printf( "\n\n=====================================================" ); - _tprintf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile ); - printf( "\n-----------------------------------------------------" ); - - // Retrieve the priority class. - dwPriorityClass = 0; - hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID ); - if (hProcess == NULL) - printError( TEXT("OpenProcess") ); - else - { - dwPriorityClass = GetPriorityClass( hProcess ); - if (!dwPriorityClass) - printError( TEXT("GetPriorityClass") ); - CloseHandle( hProcess ); - } - - printf( "\n Process ID = 0x%08X", pe32.th32ProcessID ); - printf( "\n Thread count = %d", pe32.cntThreads ); - printf( "\n Parent process ID = 0x%08X", pe32.th32ParentProcessID ); - printf( "\n Priority base = %d", pe32.pcPriClassBase ); - if (dwPriorityClass) - printf( "\n Priority class = %d", dwPriorityClass ); - - // List the modules and threads associated with this process - ListProcessModules( pe32.th32ProcessID ); - ListProcessThreads( pe32.th32ProcessID ); - - } while( Process32Next( hProcessSnap, &pe32 ) ); - - CloseHandle( hProcessSnap ); - return( TRUE ); -} - - -BOOL ListProcessModules( DWORD dwPID ) -{ - HANDLE hModuleSnap = INVALID_HANDLE_VALUE; - MODULEENTRY32 me32; - - // Take a snapshot of all modules in the specified process. - hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID ); - if (hModuleSnap == INVALID_HANDLE_VALUE) - { - printError( TEXT("CreateToolhelp32Snapshot (of modules)") ); - return( FALSE ); - } - - // Set the size of the structure before using it. - me32.dwSize = sizeof( MODULEENTRY32 ); - - // Retrieve information about the first module, - // and exit if unsuccessful - if (!Module32First( hModuleSnap, &me32 )) - { - printError( TEXT("Module32First") ); // show cause of failure - CloseHandle( hModuleSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the module list of the process, - // and display information about each module - do - { - _tprintf( TEXT("\n\n MODULE NAME: %s"), me32.szModule ); - _tprintf( TEXT("\n Executable = %s"), me32.szExePath ); - printf( "\n Process ID = 0x%08X", me32.th32ProcessID ); - printf( "\n Ref count (g) = 0x%04X", me32.GlblcntUsage ); - printf( "\n Ref count (p) = 0x%04X", me32.ProccntUsage ); - printf( "\n Base address = 0x%08X", (DWORD) me32.modBaseAddr ); - printf( "\n Base size = %d", me32.modBaseSize ); - - } while( Module32Next( hModuleSnap, &me32 ) ); - - CloseHandle( hModuleSnap ); - return( TRUE ); -} - -BOOL ListProcessThreads( DWORD dwOwnerPID ) -{ - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); - if (hThreadSnap == INVALID_HANDLE_VALUE) - return( FALSE ); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32 ); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if (!Thread32First( hThreadSnap, &te32 )) - { - printError( TEXT("Thread32First") ); // show cause of failure - CloseHandle( hThreadSnap ); // clean the snapshot object - return( FALSE ); - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if (te32.th32OwnerProcessID == dwOwnerPID) - { - printf( "\n\n THREAD ID = 0x%08X", te32.th32ThreadID ); - printf( "\n Base priority = %d", te32.tpBasePri ); - printf( "\n Delta priority = %d", te32.tpDeltaPri ); - } - } while( Thread32Next(hThreadSnap, &te32 ) ); - - CloseHandle( hThreadSnap ); - return( TRUE ); -} - -void printError( TCHAR* msg ) -{ - DWORD eNum; - TCHAR sysMsg[256]; - TCHAR* p; - - eNum = GetLastError( ); - FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, eNum, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - sysMsg, 256, NULL ); - - // Trim the end of the line and terminate it with a null - p = sysMsg; - while( ( *p > 31 ) || ( *p == 9 ) ) - ++p; - do { *p-- = 0; } while( ( p >= sysMsg ) && - ( ( *p == '.' ) || ( *p < 33 ) ) ); - - // Display the message - _tprintf( TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg ); -} - -#endif - - void AttachRemoteDialog::procSelected(const QModelIndex &index0) { QModelIndex index = index0.sibling(index0.row(), 0); From ab474061a6de718620b3756cbcbbd7bf8ecce29b Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 16:10:56 +0100 Subject: [PATCH 139/230] Pretty print declarator list. --- shared/cplusplus/PrettyPrinter.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index ab086cb74c0..213d21a468a 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -35,7 +35,6 @@ #include "AST.h" #include #include -#include CPLUSPLUS_USE_NAMESPACE @@ -385,9 +384,13 @@ bool PrettyPrinter::visit(DeclaratorIdAST *ast) return false; } -bool PrettyPrinter::visit(DeclaratorListAST *) +bool PrettyPrinter::visit(DeclaratorListAST *ast) { - assert(0); + for (DeclaratorListAST *it = ast; it; it = it->next) { + accept(it->declarator); + if (it->next) + out << ", "; + } return false; } From 7cf9888a1e2eaddf45baa2e6fa11196c032d65cc Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Mon, 5 Jan 2009 16:11:28 +0100 Subject: [PATCH 140/230] Fixed a typo in the pretty printing of TemplateTypeParameterAST. --- shared/cplusplus/PrettyPrinter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index 213d21a468a..7664d5b6d40 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -1042,7 +1042,7 @@ bool PrettyPrinter::visit(TemplateTypeParameterAST *ast) for (DeclarationAST *it = ast->template_parameters; it; it = it->next) { accept(it); if (it->next) - out << ",. "; + out << ", "; } out << ' '; } From 8e261e0b3c257779c967ce1c0ea9d0c4d2ecabe8 Mon Sep 17 00:00:00 2001 From: con Date: Mon, 5 Jan 2009 18:04:24 +0100 Subject: [PATCH 141/230] Fixes: - Start on API documentation generation --- doc/api/classic.css | 102 ++++++++++++ doc/api/qtcreator-api.qdoc | 65 ++++++++ .../qtcreator-api.qdocconf} | 156 +++++++++++++----- doc/workbench.qdoc | 98 ----------- src/libs/extensionsystem/iplugin.cpp | 2 +- src/libs/extensionsystem/pluginmanager.cpp | 11 +- src/libs/extensionsystem/pluginspec.cpp | 2 +- 7 files changed, 298 insertions(+), 138 deletions(-) create mode 100644 doc/api/classic.css create mode 100644 doc/api/qtcreator-api.qdoc rename doc/{workbench.qtdocconf => api/qtcreator-api.qdocconf} (56%) delete mode 100644 doc/workbench.qdoc diff --git a/doc/api/classic.css b/doc/api/classic.css new file mode 100644 index 00000000000..400ee71168c --- /dev/null +++ b/doc/api/classic.css @@ -0,0 +1,102 @@ +h3.fn,span.fn +{ + margin-left: 1cm; + text-indent: -1cm; +} + +a:link +{ + color: #004faf; + text-decoration: none +} + +a:visited +{ + color: #672967; + text-decoration: none +} + +td.postheader +{ + font-family: sans-serif +} + +tr.address +{ + font-family: sans-serif +} + +body +{ + background: #ffffff; + color: black +} + +table tr.odd { + background: #f0f0f0; + color: black; +} + +table tr.even { + background: #e4e4e4; + color: black; +} + +table.annotated th { + padding: 3px; + text-align: left +} + +table.annotated td { + padding: 3px; +} + +table tr pre +{ + padding-top: none; + padding-bottom: none; + padding-left: none; + padding-right: none; + border: none; + background: none +} + +tr.qt-style +{ + background: #a2c511; + color: black +} + +body pre +{ + padding: 0.2em; + border: #e7e7e7 1px solid; + background: #f1f1f1; + color: black +} + +span.preprocessor, span.preprocessor a +{ + color: darkblue; +} + +span.comment +{ + color: darkred; + font-style: italic +} + +span.string,span.char +{ + color: darkgreen; +} + +.subtitle +{ + font-size: 0.8em +} + +.small-subtitle +{ + font-size: 0.65em +} diff --git a/doc/api/qtcreator-api.qdoc b/doc/api/qtcreator-api.qdoc new file mode 100644 index 00000000000..2c939b21bb4 --- /dev/null +++ b/doc/api/qtcreator-api.qdoc @@ -0,0 +1,65 @@ +/*! + \page index.html + \title Qt Creator + + Qt Creator is Qt Software's crossplatform IDE. The core of Qt Creator is + basically only a \l{Plugin Loader Framework}{plugin loader}. + + \section1 Plugins + + As already mentioned, Qt Creator is basically only a plugin loader framework + which gets its IDE functionality through plugins. The most important plugin + is the Core plugin which provides all the basic functionality needed + later to integrate e.g. editors or mode windows. + + \table + \header + \o Plugin Name + \o Description + + \row + \o \l{Core Plugin} {Core} + \o The core plugin. Provides the main window and managers for editors, + actions, mode windows and files, just to mention the most important ones. + + \endtable + +*/ + +/*! + \page classes.html + \title Qt Creator Classes and Namespaces + + \section1 Classes + + \generatelist classes + + \section1 Namespaces + + \generatelist{namespaces} +*/ + +/*! + \page interfaces.html + \title Interfaces + \generatelist mainclasses + +*/ + +/*! + \page functions.html + \title Member Function Index + \generatelist functionindex +*/ + +/*! + \group pluginloader + + \title Plugin Loader Framework +*/ + +/*! + \group qtc + + \title Core Plugin +*/ diff --git a/doc/workbench.qtdocconf b/doc/api/qtcreator-api.qdocconf similarity index 56% rename from doc/workbench.qtdocconf rename to doc/api/qtcreator-api.qdocconf index 7a82c2aac6f..336aa27edcf 100644 --- a/doc/workbench.qtdocconf +++ b/doc/api/qtcreator-api.qdocconf @@ -1,17 +1,17 @@ -project = Workbench -description = Workbench SDK Documentation +project = Qt Creator API +description = Qt Creator API Documentation language = Cpp headerdirs = . \ - ../src/libs/extensionsystem \ - ../src/plugins/core \ - ../src/plugins/core/actionmanager + ../../src/libs/extensionsystem \ + ../../src/plugins/core \ + ../../src/plugins/core/actionmanager sourcedirs = . \ - ../src/libs/extensionsystem \ - ../src/plugins/core \ - ../src/plugins/core/actionmanager + ../../src/libs/extensionsystem \ + ../../src/plugins/core \ + ../../src/plugins/core/actionmanager headers.fileextesnions = "*.h" sources.fileextensions = "*.cpp *.qdoc" @@ -20,35 +20,72 @@ imagedirs = . indexes = $QTDIR/doc/html/qt.index -outputdir = ./html -base = file:./html -versionsym = 1.0.0 -defines = Q_QDOC \ - QT_.*_SUPPORT \ - QT_.*_LIB \ - QT_COMPAT \ - QT_KEYPAD_NAVIGATION \ - QT3_SUPPORT \ - Q_WS_.* \ - Q_OS_.* \ - Q_BYTE_ORDER \ - __cplusplus - +outputdir = ./html-api +base = file:./html-api +versionsym = 0.9.2 codeindent = 1 -extraimages.HTML = qt-logo \ - trolltech-logo -macro.br.HTML = "
" -macro.QD = "\\e{Qt Designer}" -macro.QA = "\\e{Qt Assistant}" -macro.eacute.HTML = "é" +## compat.qdocconf +alias.i = e +alias.include = input + +macro.0 = "\\\\0" +macro.b = "\\\\b" +macro.n = "\\\\n" +macro.r = "\\\\r" +macro.i = "\\o" +macro.i11 = "\\o{1,1}" +macro.i12 = "\\o{1,2}" +macro.i13 = "\\o{1,3}" +macro.i14 = "\\o{1,4}" +macro.i15 = "\\o{1,5}" +macro.i16 = "\\o{1,6}" +macro.i17 = "\\o{1,7}" +macro.i18 = "\\o{1,8}" +macro.i19 = "\\o{1,9}" +macro.i21 = "\\o{2,1}" +macro.i31 = "\\o{3,1}" +macro.i41 = "\\o{4,1}" +macro.i51 = "\\o{5,1}" +macro.i61 = "\\o{6,1}" +macro.i71 = "\\o{7,1}" +macro.i81 = "\\o{8,1}" +macro.i91 = "\\o{9,1}" +macro.img = "\\image" +macro.endquote = "\\endquotation" +macro.relatesto = "\\relates" + +spurious = "Missing comma in .*" \ + "Missing pattern .*" + +## macros.qdocconf macro.aring.HTML = "å" +macro.Auml.HTML = "Ä" +macro.author = "\\bold{Author:}" +macro.br.HTML = "
" +macro.BR.HTML = "
" +macro.aacute.HTML = "á" +macro.eacute.HTML = "é" +macro.iacute.HTML = "í" +macro.gui = "\\bold" +macro.hr.HTML = "
" +macro.key = "\\bold" +macro.menu = "\\bold" +macro.note = "\\bold{Note:}" macro.oslash.HTML = "ø" macro.ouml.HTML = "ö" -macro.Auml.HTML = "Ä" -macro.uuml.HTML = "ü" +macro.QA = "\\e{Qt Assistant}" +macro.QD = "\\e{Qt Designer}" +macro.QL = "\\e{Qt Linguist}" +macro.param = "\\e" +macro.raisedaster.HTML = "*" +macro.reg.HTML = "®" +macro.return = "Returns" macro.starslash = "\\c{*/}" +macro.uuml.HTML = "ü" +macro.mdash.HTML = "—" +## qt-cpp-ignore.qdocconf Cpp.ignoretokens = QAXFACTORY_EXPORT \ QDESIGNER_COMPONENTS_LIBRARY \ QDESIGNER_EXTENSION_LIBRARY \ @@ -68,9 +105,11 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ QM_EXPORT_WORKSPACE \ QM_EXPORT_XML \ QT_ASCII_CAST_WARN \ + QT_ASCII_CAST_WARN_CONSTRUCTOR \ QT_BEGIN_HEADER \ QT_DESIGNER_STATIC \ QT_END_HEADER \ + QT_FASTCALL \ QT_WIDGET_PLUGIN_EXPORT \ Q_COMPAT_EXPORT \ Q_CORE_EXPORT \ @@ -81,6 +120,7 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ Q_EXPORT_CODECS_KR \ Q_EXPORT_PLUGIN \ Q_GFX_INLINE \ + Q_AUTOTEST_EXPORT \ Q_GUI_EXPORT \ Q_GUI_EXPORT_INLINE \ Q_GUI_EXPORT_STYLE_CDE \ @@ -93,17 +133,27 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ Q_GUI_EXPORT_STYLE_SGI \ Q_GUI_EXPORT_STYLE_WINDOWS \ Q_GUI_EXPORT_STYLE_WINDOWSXP \ + QHELP_EXPORT \ Q_INLINE_TEMPLATE \ + Q_INTERNAL_WIN_NO_THROW \ Q_NETWORK_EXPORT \ Q_OPENGL_EXPORT \ Q_OUTOFLINE_TEMPLATE \ Q_SQL_EXPORT \ Q_SVG_EXPORT \ Q_SCRIPT_EXPORT \ + Q_SCRIPTTOOLS_EXPORT \ Q_TESTLIB_EXPORT \ Q_TYPENAME \ Q_XML_EXPORT \ - QDBUS_EXPORT + Q_XMLSTREAM_EXPORT \ + Q_XMLPATTERNS_EXPORT \ + QDBUS_EXPORT \ + QT_BEGIN_NAMESPACE \ + QT_BEGIN_INCLUDE_NAMESPACE \ + QT_END_NAMESPACE \ + QT_END_INCLUDE_NAMESPACE \ + PHONON_EXPORT Cpp.ignoredirectives = Q_DECLARE_HANDLE \ Q_DECLARE_INTERFACE \ Q_DECLARE_METATYPE \ @@ -114,34 +164,66 @@ Cpp.ignoredirectives = Q_DECLARE_HANDLE \ Q_DECLARE_TR_FUNCTIONS \ Q_DECLARE_TYPEINFO \ Q_DISABLE_COPY \ + QT_FORWARD_DECLARE_CLASS \ Q_DUMMY_COMPARISON_OPERATOR \ Q_ENUMS \ Q_FLAGS \ Q_INTERFACES \ - __attribute__ + __attribute__ \ + K_DECLARE_PRIVATE \ + PHONON_OBJECT \ + PHONON_HEIR +## qt-html-templates.qdocconf HTML.stylesheets = classic.css HTML.postheader = "\n" \ "\n" \ "\n" \ "" \ "\n" \ - "
" \ - "" \ + "" \ "  " \ "" \ "Home ·" \ + " " \ + "All Namespaces ·" \ " " \ "All Classes ·" \ - " " \ - "All Interfaces ·" \ + " " \ + "Main Classes ·" \ + " " \ + "Grouped Classes ·" \ + " " \ + "Modules ·" \ " " \ "Functions" \ "
" + "" HTML.footer = "


\n" \ "\n" \ - "\n" \ + "\n" \ "\n" \ "\n" \ "
Copyright © \$THISYEAR\$ TrolltechCopyright © %THISYEAR% Nokia Corporation " \ + "and/or its subsidiary(-ies)Trademarks
Qt \\version
" + +## qt-defines.qdocconf +defines = Q_QDOC \ + QT_.*_SUPPORT \ + QT_.*_LIB \ + QT_COMPAT \ + QT_KEYPAD_NAVIGATION \ + QT3_SUPPORT \ + Q_WS_.* \ + Q_OS_.* \ + Q_BYTE_ORDER \ + QT_DEPRECATED \ + Q_NO_USING_KEYWORD \ + __cplusplus + +# Files not referenced in any qdoc file (last four needed by qtdemo) +# See also qhp.Qt.extraFiles +extraimages.HTML = qt-logo \ + trolltech-logo + diff --git a/doc/workbench.qdoc b/doc/workbench.qdoc deleted file mode 100644 index 033b1ae7d4b..00000000000 --- a/doc/workbench.qdoc +++ /dev/null @@ -1,98 +0,0 @@ -/*! - \page index.html - \title Workbench - - Workbench is Trolltech's crossplatform IDE. The core of Workbench is - basically only a \l{Plugin Loader Framework}{plugin loader} comparable to - Eclipse. All major functionality is then added via plugins. The plugins - necessary for a full IDE will be provided by Trolltech, possible addons or - replacements of existing plugins can be provided by anyone. This means that - there will be a place where plugins can be shared. - - The main features of Workbench are: - - \list - \o Fast since it's written in C++ - \o Easy and fast to use (the entire IDE can be controlled via short cuts) - \o Highly extensible - \o Integrated C++ language support, i.e. code completion, class browser, ... - \o Integrated debugger framework and outstanding support for gdb - \o Integrated Qt Designer - \o Qtopia Integration - \endlist - - \section1 Plugins - - As already mentioned, Workbench is basically only a plugin loader framework - which gets its IDE functionality through plugins. The most important plugin - is the QWorkbench plugin which provides all the basic functionality needed - later to integrate e.g. editors or tool windows. - - \table - \header - \o Plugin Name - \o Description - - \row - \o \l{QWorkbench Plugin} {QWorkbench} - \o The core plugin. Provides the main window and managers for editors, - actions, tool windows and files, just to mention the most important ones. - - \endtable - -*/ - -/*! - \page classes.html - \title Workbench Classes and Namespaces - - \section1 Classes - - \generatelist classes - - \section1 Namespaces - - \generatelist{namespaces} -*/ - -/*! - \page interfaces.html - \title Interfaces - \generatelist mainclasses - -*/ - -/*! - \page functions.html - \title Member Function Index - \generatelist functionindex -*/ - -/*! - \group pluginloader - - \title Plugin Loader Framework -*/ - -/*! - \group qwb - - \title QWorkbench Plugin -*/ - -/*! - \namespace Trolltech -*/ - -/*! - \namespace Trolltech::QWorkbench -*/ - -/*! - \namespace Trolltech::QWorkbench::Internal - \brief Classes that manage and control internal features of the workbench environment. -*/ - -/*! - \namespace ExtensionSystem -*/ diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp index 1b75839fa89..70d2366ea9a 100644 --- a/src/libs/extensionsystem/iplugin.cpp +++ b/src/libs/extensionsystem/iplugin.cpp @@ -304,7 +304,7 @@ void IPlugin::addObject(QObject *obj) plugin pool. Usually, registered objects must be removed from the object pool and deleted by hand. Objects added to the pool via addAutoReleasedObject are automatically - removed and deleted in \i reverse order of registration when + removed and deleted in reverse order of registration when the IPlugin instance is destroyed. \sa PluginManager::addObject() */ diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index 0603cd87cab..7dc9c4e10af 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -54,7 +54,8 @@ enum { debugLeaks = 0 }; /*! \namespace ExtensionSystem - \brief Classes that belong to the core plugin system. + \brief The ExtensionSystem namespace provides + classes that belong to the core plugin system. The basic extension system contains of the plugin manager and its supporting classes, and the IPlugin interface that must be implemented by plugin providers. @@ -444,11 +445,19 @@ void PluginManager::startTests() #endif } +/*! + * \fn bool PluginManager::runningTests() const + * \internal + */ bool PluginManager::runningTests() const { return !d->testSpecs.isEmpty(); } +/*! + * \fn QString PluginManager::testDataDirectory() const + * \internal + */ QString PluginManager::testDataDirectory() const { QString s = QString::fromLocal8Bit(qgetenv("IDETESTDIR")); diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp index 99e83d9fc64..0e5fa53996f 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -221,7 +221,7 @@ QList PluginSpec::dependencies() const } /*! - \fn PluginOptionDescriptions optionDescriptions() const + \fn PluginSpec::PluginArgumentDescriptions PluginSpec::argumentDescriptions() const Returns a list of descriptions of command line arguments the plugin processes. */ From 1187e56ba5dca6f3e0ef48d04b37331dab50e563 Mon Sep 17 00:00:00 2001 From: mae Date: Mon, 5 Jan 2009 18:28:56 +0100 Subject: [PATCH 142/230] added missing cassert include --- shared/cplusplus/PrettyPrinter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index 7664d5b6d40..d6addb855b0 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -35,6 +35,7 @@ #include "AST.h" #include #include +#include CPLUSPLUS_USE_NAMESPACE From 37c67ccd98c125147484c6c6a571fa7393179c67 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 10:22:21 +0100 Subject: [PATCH 143/230] remove unused mode.ui --- src/plugins/debugger/debugger.pro | 1 - src/plugins/debugger/mode.ui | 76 ------------------------------- 2 files changed, 77 deletions(-) delete mode 100644 src/plugins/debugger/mode.ui diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index 7308fb441c2..b47e7d5ee02 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -76,7 +76,6 @@ FORMS += attachexternaldialog.ui \ attachremotedialog.ui \ breakbyfunction.ui \ breakcondition.ui \ - mode.ui \ gdboptionpage.ui \ startexternaldialog.ui \ diff --git a/src/plugins/debugger/mode.ui b/src/plugins/debugger/mode.ui deleted file mode 100644 index da44cf38b4a..00000000000 --- a/src/plugins/debugger/mode.ui +++ /dev/null @@ -1,76 +0,0 @@ - - DebugMode - - - - 0 - 0 - 558 - 353 - - - - Form - - - - 0 - - - 0 - - - - - Qt::Vertical - - - - - 10 - 10 - - - - - - - 0 - - - - - 0 - - - - - - - Qt::Horizontal - - - - - 0 - 0 - - - - QTabWidget::South - - - QTabWidget::Rounded - - - - - - - - - - - - - From d7bd3a0a2d15d37218604823d813aa25a8f30c8e Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:11:31 +0100 Subject: [PATCH 144/230] whitespace fixes --- src/plugins/fakevim/handler.cpp | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index fd8734f2114..16550f5ef58 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -132,14 +132,14 @@ public: int lastPositionInDocument() const; - // all zero-based counting - int cursorLineOnScreen() const; - int linesOnScreen() const; - int columnsOnScreen() const; - int cursorLineInDocument() const; - int cursorColumnInDocument() const; + // all zero-based counting + int cursorLineOnScreen() const; + int linesOnScreen() const; + int columnsOnScreen() const; + int cursorLineInDocument() const; + int cursorColumnInDocument() const; int linesInDocument() const; - void scrollToLineInDocument(int line); + void scrollToLineInDocument(int line); void moveToFirstNonBlankOnLine(); void moveToNextWord(bool simple); @@ -343,7 +343,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (m_submode == ZSubMode) { if (key == Key_Return) { // cursor line to top of window, cursor on first non-blank - scrollToLineInDocument(cursorLineInDocument()); + scrollToLineInDocument(cursorLineInDocument()); moveToFirstNonBlankOnLine(); finishMovement(); } else { @@ -961,30 +961,30 @@ void FakeVimHandler::Private::moveToNextWord(bool simple) int FakeVimHandler::Private::cursorLineOnScreen() const { - QRect rect = EDITOR(cursorRect()); - return rect.y() / rect.height(); + QRect rect = EDITOR(cursorRect()); + return rect.y() / rect.height(); } int FakeVimHandler::Private::linesOnScreen() const { - QRect rect = EDITOR(cursorRect()); - return EDITOR(height()) / rect.height(); + QRect rect = EDITOR(cursorRect()); + return EDITOR(height()) / rect.height(); } int FakeVimHandler::Private::columnsOnScreen() const { - QRect rect = EDITOR(cursorRect()); - return EDITOR(width()) / rect.width(); + QRect rect = EDITOR(cursorRect()); + return EDITOR(width()) / rect.width(); } int FakeVimHandler::Private::cursorLineInDocument() const { - return m_tc.block().blockNumber(); + return m_tc.block().blockNumber(); } int FakeVimHandler::Private::cursorColumnInDocument() const { - return m_tc.position() - m_tc.block().position(); + return m_tc.position() - m_tc.block().position(); } int FakeVimHandler::Private::linesInDocument() const @@ -994,9 +994,9 @@ int FakeVimHandler::Private::linesInDocument() const void FakeVimHandler::Private::scrollToLineInDocument(int line) { - // FIXME: works only for QPlainTextEdit - QScrollBar *scrollBar = EDITOR(verticalScrollBar()); - scrollBar->setValue(line); + // FIXME: works only for QPlainTextEdit + QScrollBar *scrollBar = EDITOR(verticalScrollBar()); + scrollBar->setValue(line); } int FakeVimHandler::Private::lastPositionInDocument() const From bdfd5cada19a194484214544510f3cfa02ea79ac Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:33:07 +0100 Subject: [PATCH 145/230] implement :d, also uses ranges for :w! --- src/plugins/fakevim/handler.cpp | 46 ++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 16550f5ef58..1e8931cb83a 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include @@ -131,6 +132,7 @@ public: bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; } int lastPositionInDocument() const; + int positionForLine(int line) const; // 1 based // all zero-based counting int cursorLineOnScreen() const; @@ -149,6 +151,7 @@ public: // helper function for handleCommand. return 1 based line index. int readLineCode(QString &cmd); + QTextCursor selectRange(int beginLine, int endLine); FakeVimHandler *q; Mode m_mode; @@ -360,7 +363,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (m_subsubmode == BackTickSubSubMode || m_subsubmode == TickSubSubMode) { if (m_marks.contains(key)) { - m_tc.setPosition(m_marks[key]); + m_tc.setPosition(m_marks[key], MoveAnchor); if (m_subsubmode == TickSubSubMode) moveToFirstNonBlankOnLine(); finishMovement(); @@ -453,7 +456,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_gflag = true; } else if (key == 'G') { int n = m_mvcount.isEmpty() ? linesInDocument() : count(); - m_tc.setPosition(m_tc.document()->findBlockByNumber(n - 1).position()); + m_tc.setPosition(positionForLine(n), MoveAnchor); if (m_config.contains(ConfigStartOfLine)) moveToFirstNonBlankOnLine(); finishMovement(); @@ -754,6 +757,14 @@ int FakeVimHandler::Private::readLineCode(QString &cmd) return -1; } +QTextCursor FakeVimHandler::Private::selectRange(int beginLine, int endLine) +{ + QTextCursor tc = m_tc; + tc.setPosition(positionForLine(beginLine), MoveAnchor); + tc.setPosition(positionForLine(endLine + 1), KeepAnchor); + return tc; +} + void FakeVimHandler::Private::handleCommand(const QString &cmd0) { QString cmd = cmd0; @@ -777,15 +788,29 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) //qDebug() << "RANGE: " << beginLine << endLine << cmd << cmd0; static QRegExp reWrite("^w!?( (.*))?$"); + static QRegExp reDelete("^d( (.*))?$"); if (cmd.isEmpty()) { - m_tc.setPosition(m_tc.block().document() - ->findBlockByNumber(beginLine - 1).position()); + m_tc.setPosition(positionForLine(beginLine)); showMessage(QString()); - } else if (cmd == "q!" || cmd == "q") { + } else if (cmd == "q!" || cmd == "q") { // :q q->quitRequested(THE_EDITOR); showMessage(QString()); - } else if (reWrite.indexIn(cmd) != -1) { + } else if (reDelete.indexIn(cmd) != -1) { // :d + if (beginLine == -1) + beginLine = cursorLineInDocument(); + if (endLine == -1) + endLine = cursorLineInDocument(); + QTextCursor tc = selectRange(beginLine, endLine); + QString reg = reDelete.cap(2); + if (!reg.isEmpty()) + m_registers[reg.at(0).unicode()] = tc.selection().toPlainText(); + tc.removeSelectedText(); + } else if (reWrite.indexIn(cmd) != -1) { // :w + if (beginLine == -1) + beginLine = 0; + if (endLine == -1) + endLine = linesInDocument(); bool forced = cmd.startsWith("w!"); QString fileName = reWrite.cap(2); if (fileName.isEmpty()) @@ -796,8 +821,10 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) showMessage("E13: File exists (add ! to override)"); } else { file.open(QIODevice::ReadWrite); + QTextCursor tc = selectRange(beginLine, endLine); + QString text = tc.selection().toPlainText(); QTextStream ts(&file); - ts << EDITOR(toPlainText()); + ts << text; file.close(); file.open(QIODevice::ReadWrite); QByteArray ba = file.readAll(); @@ -1010,6 +1037,11 @@ QString FakeVimHandler::Private::lastSearchString() const return m_searchHistory.empty() ? QString() : m_searchHistory.back(); } +int FakeVimHandler::Private::positionForLine(int line) const +{ + return m_tc.block().document()->findBlockByNumber(line - 1).position(); +} + /////////////////////////////////////////////////////////////////////// // // FakeVimHandler From c729ff0f0bd935c07cafc081843c2bb7d07a8962 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:37:24 +0100 Subject: [PATCH 146/230] use better a default range for :d --- src/plugins/fakevim/handler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 1e8931cb83a..88f7eaa31f8 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -771,8 +771,8 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) if (cmd.startsWith("%")) cmd = "1,$" + cmd.mid(1); - int beginLine = 0; - int endLine = linesInDocument(); + int beginLine = -1; + int endLine = -1; int line = readLineCode(cmd); if (line != -1) From 417032d187d4963917a17664c025bb0a15baf56f Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:42:44 +0100 Subject: [PATCH 147/230] 'd' works, but no visual feedback so far --- src/plugins/fakevim/handler.cpp | 77 +++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 13 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 88f7eaa31f8..229df5a0395 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -132,7 +132,8 @@ public: bool atEol() const { return m_tc.atBlockEnd() && m_tc.block().length()>1; } int lastPositionInDocument() const; - int positionForLine(int line) const; // 1 based + int positionForLine(int line) const; // 1 based line, 0 based pos + int lineForPosition(int pos) const; // 1 based line, 0 based pos // all zero-based counting int cursorLineOnScreen() const; @@ -184,15 +185,20 @@ public: bool m_lastSearchForward; QString m_lastInsertion; - // History for '/' + // history for '/' QString lastSearchString() const; QStringList m_searchHistory; int m_searchHistoryIndex; - // History for ':' + // history for ':' QStringList m_commandHistory; int m_commandHistoryIndex; + // visual line mode + void enterVisualLineMode(); + void leaveVisualLineMode(); + bool m_visualLineMode; + // marks as lines QHash m_marks; @@ -214,6 +220,7 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) m_gflag = false; m_textedit = 0; m_plaintextedit = 0; + m_visualLineMode = false; m_config[ConfigStartOfLine] = ConfigOn; } @@ -292,7 +299,12 @@ void FakeVimHandler::Private::updateMiniBuffer() if (m_tc.isNull()) return; QString msg; - if (m_currentMessage.isEmpty()) { + if (!m_currentMessage.isEmpty()) { + msg = m_currentMessage; + m_currentMessage.clear(); + } else if (m_visualLineMode) { + msg = "-- VISUAL LINE--"; + } else { msg = QChar(m_commandCode ? m_commandCode : ' '); for (int i = 0; i != m_commandBuffer.size(); ++i) { QChar c = m_commandBuffer.at(i); @@ -303,9 +315,6 @@ void FakeVimHandler::Private::updateMiniBuffer() msg += c; } } - } else { - msg = m_currentMessage; - m_currentMessage.clear(); } int l = cursorLineInDocument(); int w = columnsOnScreen(); @@ -433,11 +442,19 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(EndOfLine, KeepAnchor); finishMovement(); } else if (key == 'd') { - if (atEol()) - m_tc.movePosition(Left, MoveAnchor, 1); - m_opcount = m_mvcount; - m_mvcount.clear(); - m_submode = DeleteSubMode; + if (m_visualLineMode) { + leaveVisualLineMode(); + int beginLine = lineForPosition(m_marks['<']); + int endLine = lineForPosition(m_marks['>']); + m_tc = selectRange(beginLine, endLine); + m_tc.removeSelectedText(); + } else { + if (atEol()) + m_tc.movePosition(Left, MoveAnchor, 1); + m_opcount = m_mvcount; + m_mvcount.clear(); + m_submode = DeleteSubMode; + } } else if (key == 'D') { m_submode = DeleteSubMode; m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0)); @@ -559,6 +576,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_subsubdata = key; } else if (key == 'u') { EDITOR(undo()); + } else if (key == 'V') { + enterVisualLineMode(); } else if (key == 'w') { moveToNextWord(false); finishMovement(); @@ -599,7 +618,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == Key_Delete) { m_tc.deleteChar(); } else if (key == Key_Escape) { - // harmless + if (m_visualLineMode) + leaveVisualLineMode(); } else { qDebug() << "Ignored" << key << text; } @@ -740,6 +760,15 @@ int FakeVimHandler::Private::readLineCode(QString &cmd) int n = readLineCode(cmd); return cursorLineInDocument() + 1 + (n == -1 ? 1 : n); } + if (c == '\'' && !cmd.isEmpty()) { + int pos = m_marks.value(cmd.at(0).unicode()); + if (!pos) { + showMessage(tr("E20: Mark '%1' not set").arg(cmd.at(0))); + return -1; + } + cmd = cmd.mid(1); + return lineForPosition(pos); + } if (c.isDigit()) { int n = c.unicode() - '0'; while (!cmd.isEmpty()) { @@ -1042,6 +1071,28 @@ int FakeVimHandler::Private::positionForLine(int line) const return m_tc.block().document()->findBlockByNumber(line - 1).position(); } +int FakeVimHandler::Private::lineForPosition(int pos) const +{ + QTextCursor tc = m_tc; + tc.setPosition(pos); + return tc.block().blockNumber() + 1; +} + +void FakeVimHandler::Private::enterVisualLineMode() +{ + m_visualLineMode = true; + m_marks['<'] = m_tc.position(); + updateMiniBuffer(); +} + +void FakeVimHandler::Private::leaveVisualLineMode() +{ + m_visualLineMode = false; + m_marks['>'] = m_tc.position(); + updateMiniBuffer(); +} + + /////////////////////////////////////////////////////////////////////// // // FakeVimHandler From 1caa69f2414d00cd0f2fd64ef5f57843c70f4c12 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:43:27 +0100 Subject: [PATCH 148/230] replace a macro with a proper function --- src/plugins/fakevim/handler.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 229df5a0395..1dfbb11bd61 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -69,7 +69,6 @@ using namespace FakeVim::Internal; /////////////////////////////////////////////////////////////////////// #define EDITOR(s) (m_textedit ? m_textedit->s : m_plaintextedit->s) -#define THE_EDITOR (m_textedit ? (QWidget*)m_textedit : (QWidget*)m_plaintextedit) const int ParagraphSeparator = 0x00002029; @@ -173,6 +172,7 @@ public: bool m_fakeEnd; + QWidget *editor(); bool isSearchCommand() const { return m_commandCode == '?' || m_commandCode == '/'; } int m_commandCode; // ?, /, : ... @@ -823,7 +823,7 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) m_tc.setPosition(positionForLine(beginLine)); showMessage(QString()); } else if (cmd == "q!" || cmd == "q") { // :q - q->quitRequested(THE_EDITOR); + q->quitRequested(editor()); showMessage(QString()); } else if (reDelete.indexIn(cmd) != -1) { // :d if (beginLine == -1) @@ -1092,6 +1092,12 @@ void FakeVimHandler::Private::leaveVisualLineMode() updateMiniBuffer(); } +QWidget *FakeVimHandler::Private::editor() +{ + return m_textedit + ? static_cast(m_textedit) + : static_cast(m_plaintextedit); +} /////////////////////////////////////////////////////////////////////// // From 8f4818989aa0756d7455de7ace68098d5590ba5f Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:43:49 +0100 Subject: [PATCH 149/230] start with '.' --- src/plugins/fakevim/handler.cpp | 62 +++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 1dfbb11bd61..5d26971f8a5 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -118,7 +118,7 @@ public: void handleCommandMode(int key, const QString &text); void handleRegisterMode(int key, const QString &text); void handleExMode(int key, const QString &text); - void finishMovement(); + void finishMovement(const QString &text = QString()); void updateMiniBuffer(); void search(const QString &needle, bool forward); void showMessage(const QString &msg); @@ -185,6 +185,10 @@ public: bool m_lastSearchForward; QString m_lastInsertion; + // extra data for '.' + QString m_dotCount; + QString m_dotCommand; + // history for '/' QString lastSearchString() const; QStringList m_searchHistory; @@ -272,14 +276,18 @@ void FakeVimHandler::Private::handleKey(int key, const QString &text) handleExMode(key, text); } -void FakeVimHandler::Private::finishMovement() +void FakeVimHandler::Private::finishMovement(const QString &dotCommand) { if (m_submode == ChangeSubMode) { + if (!dotCommand.isEmpty()) + m_dotCommand = "c" + dotCommand; m_registers[m_register] = m_tc.selectedText(); m_tc.removeSelectedText(); m_mode = InsertMode; m_submode = NoSubMode; } else if (m_submode == DeleteSubMode) { + if (!dotCommand.isEmpty()) + m_dotCommand = "d" + dotCommand; m_registers[m_register] = m_tc.selectedText(); m_tc.removeSelectedText(); m_submode = NoSubMode; @@ -346,12 +354,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(StartOfLine, MoveAnchor); m_tc.movePosition(Down, KeepAnchor, count()); m_registers[m_register] = m_tc.selectedText(); - finishMovement(); + finishMovement("c"); } else if (m_submode == DeleteSubMode && key == 'd') { m_tc.movePosition(StartOfLine, MoveAnchor); m_tc.movePosition(Down, KeepAnchor, count()); m_registers[m_register] = m_tc.selectedText(); - finishMovement(); + finishMovement("d"); } else if (m_submode == ZSubMode) { if (key == Key_Return) { // cursor line to top of window, cursor on first non-blank @@ -365,7 +373,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (m_subsubmode == FtSubSubMode) { handleFfTt(key); m_subsubmode = NoSubSubMode; - finishMovement(); + finishMovement(QString(QChar(m_subsubdata)) + QChar(key)); } else if (m_subsubmode == MarkSubSubMode) { m_marks[key] = m_tc.position(); m_subsubmode = NoSubSubMode; @@ -417,6 +425,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == '$' || key == Key_End) { m_tc.movePosition(EndOfLine, KeepAnchor); finishMovement(); + } else if (key == '.') { + qDebug() << "REPEATING" << m_dotCommand; + for (int i = count(); --i >= 0; ) + foreach (QChar c, m_dotCommand) + handleKey(c.unicode(), QString(c)); } else if (key == 'a') { m_mode = InsertMode; m_lastInsertion.clear(); @@ -438,23 +451,21 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.beginEditBlock(); } else if (key == 'C') { m_submode = ChangeSubMode; - m_tc.beginEditBlock(); + //m_tc.beginEditBlock(); m_tc.movePosition(EndOfLine, KeepAnchor); finishMovement(); + } else if (key == 'd' && m_visualLineMode) { + leaveVisualLineMode(); + int beginLine = lineForPosition(m_marks['<']); + int endLine = lineForPosition(m_marks['>']); + m_tc = selectRange(beginLine, endLine); + m_tc.removeSelectedText(); } else if (key == 'd') { - if (m_visualLineMode) { - leaveVisualLineMode(); - int beginLine = lineForPosition(m_marks['<']); - int endLine = lineForPosition(m_marks['>']); - m_tc = selectRange(beginLine, endLine); - m_tc.removeSelectedText(); - } else { - if (atEol()) - m_tc.movePosition(Left, MoveAnchor, 1); - m_opcount = m_mvcount; - m_mvcount.clear(); - m_submode = DeleteSubMode; - } + if (atEol()) + m_tc.movePosition(Left, MoveAnchor, 1); + m_opcount = m_mvcount; + m_mvcount.clear(); + m_submode = DeleteSubMode; } else if (key == 'D') { m_submode = DeleteSubMode; m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0)); @@ -490,7 +501,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key == 'i') { m_mode = InsertMode; - m_tc.beginEditBlock(); + //m_tc.beginEditBlock(); m_lastInsertion.clear(); } else if (key == 'I') { m_mode = InsertMode; @@ -499,7 +510,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) else moveToFirstNonBlankOnLine(); m_tc.clearSelection(); - m_tc.beginEditBlock(); + //m_tc.beginEditBlock(); m_lastInsertion.clear(); } else if (key == 'j' || key == Key_Down) { m_tc.movePosition(Down, KeepAnchor, count()); @@ -568,9 +579,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) EDITOR(redo()); } else if (key == 's') { m_submode = ChangeSubMode; - m_tc.beginEditBlock(); + //m_tc.beginEditBlock(); m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); - finishMovement(); } else if (key == 't' || key == 'T') { m_subsubmode = FtSubSubMode; m_subsubdata = key; @@ -580,16 +590,16 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) enterVisualLineMode(); } else if (key == 'w') { moveToNextWord(false); - finishMovement(); + finishMovement("w"); } else if (key == 'W') { moveToNextWord(true); - finishMovement(); + finishMovement("W"); } else if (key == 'x') { // = "dl" if (atEol()) m_tc.movePosition(Left, MoveAnchor, 1); m_submode = DeleteSubMode; m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); - finishMovement(); + finishMovement("l"); } else if (key == 'X') { if (leftDist() > 0) { m_tc.movePosition(Left, KeepAnchor, qMin(count(), leftDist())); From 6f8b3d3d2dc65f1c2019c99d500de35261dcb3d6 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:30:42 +0100 Subject: [PATCH 150/230] Implemented NewExpressionAST::lastToken() and NewInitializerAST::lastToken(). --- shared/cplusplus/AST.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index dcf32573616..96b941fddf6 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1860,7 +1860,6 @@ unsigned NewExpressionAST::firstToken() const unsigned NewExpressionAST::lastToken() const { - assert(0 && "review me"); if (new_initializer) return new_initializer->lastToken(); else if (new_type_id) @@ -1869,7 +1868,12 @@ unsigned NewExpressionAST::lastToken() const return type_id->lastToken(); else if (expression) return expression->lastToken(); - return new_token + 1; + else if (new_token) + return new_token + 1; + else if (scope_token) + return scope_token + 1; + // ### assert? + return 0; } void NewInitializerAST::accept0(ASTVisitor *visitor) @@ -1886,8 +1890,11 @@ unsigned NewInitializerAST::firstToken() const unsigned NewInitializerAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + return lparen_token + 1; } void NewTypeIdAST::accept0(ASTVisitor *visitor) From b563081e26cc2f128a459a07269e56457a796852 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:38:38 +0100 Subject: [PATCH 151/230] More *AST::lastToken(). --- shared/cplusplus/AST.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 96b941fddf6..6f2e69ea3fa 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1914,7 +1914,6 @@ unsigned NewTypeIdAST::firstToken() const unsigned NewTypeIdAST::lastToken() const { - assert(0 && "review me"); if (new_declarator) return new_declarator->lastToken(); else if (new_initializer) @@ -1923,6 +1922,8 @@ unsigned NewTypeIdAST::lastToken() const if (! it->next) return it->lastToken(); } + + // ### assert? return 0; } @@ -1939,7 +1940,6 @@ unsigned NumericLiteralAST::firstToken() const unsigned NumericLiteralAST::lastToken() const { - assert(0 && "review me"); return token + 1; } @@ -1956,9 +1956,10 @@ unsigned OperatorAST::firstToken() const unsigned OperatorAST::lastToken() const { - assert(0 && "review me"); if (close_token) return close_token + 1; + else if (open_token) + return open_token + 1; return op_token + 1; } @@ -1976,7 +1977,6 @@ unsigned OperatorFunctionIdAST::firstToken() const unsigned OperatorFunctionIdAST::lastToken() const { - assert(0 && "review me"); if (op) return op->lastToken(); return operator_token + 1; From 57cf35a37a28bb1291ef90d7db3dc0afcdf82cd6 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:40:54 +0100 Subject: [PATCH 152/230] ParamterDeclarationAST::lastToken() and ParameterDeclarationClauseAST::lastToken(). --- shared/cplusplus/AST.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 6f2e69ea3fa..71b1bd041ba 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1999,17 +1999,17 @@ unsigned ParameterDeclarationAST::firstToken() const unsigned ParameterDeclarationAST::lastToken() const { - assert(0 && "review me"); if (expression) return expression->lastToken(); else if (equal_token) return equal_token + 1; else if (declarator) return declarator->lastToken(); - for (SpecifierAST *it = type_specifier; it; it = it->next) { + for (SpecifierAST *it = type_specifier; it; it = it->next) { if (! it->next) return it->lastToken(); } + // ### assert? return 0; } @@ -2031,7 +2031,6 @@ unsigned ParameterDeclarationClauseAST::firstToken() const unsigned ParameterDeclarationClauseAST::lastToken() const { - assert(0 && "review me"); if (dot_dot_dot_token) return dot_dot_dot_token + 1; return parameter_declarations->lastToken(); From e0c1943c5ce298748f069f68e29812d6eeac9491 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:43:15 +0100 Subject: [PATCH 153/230] PointerToMemberAST::lastToken(). --- shared/cplusplus/AST.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 71b1bd041ba..13098ffa9d7 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2052,7 +2052,6 @@ unsigned PointerAST::firstToken() const unsigned PointerAST::lastToken() const { - assert(0 && "review me"); for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { if (! it->next) return it->lastToken(); @@ -2081,12 +2080,23 @@ unsigned PointerToMemberAST::firstToken() const unsigned PointerToMemberAST::lastToken() const { - assert(0 && "review me"); for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) { if (! it->next) return it->lastToken(); } - return star_token + 1; + + if (star_token) + return star_token + 1; + + for (NestedNameSpecifierAST *it = nested_name_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (global_scope_token) + return global_scope_token + 1; + + return 0; } void PostIncrDecrAST::accept0(ASTVisitor *visitor) From 5a06e283e8777069b64891c0dfc05c97960866a6 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:45:04 +0100 Subject: [PATCH 154/230] QualifiedNameAST::lastToken(). --- shared/cplusplus/AST.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 13098ffa9d7..b6ddde0c0eb 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2112,7 +2112,6 @@ unsigned PostIncrDecrAST::firstToken() const unsigned PostIncrDecrAST::lastToken() const { - assert(0 && "review me"); return incr_decr_token + 1; } @@ -2132,7 +2131,6 @@ unsigned PostfixExpressionAST::firstToken() const unsigned PostfixExpressionAST::lastToken() const { - assert(0 && "review me"); for (PostfixAST *it = postfix_expressions; it; it = it->next) { if (! it->next) return it->lastToken(); @@ -2159,12 +2157,18 @@ unsigned QualifiedNameAST::firstToken() const unsigned QualifiedNameAST::lastToken() const { - assert(0 && "review me"); if (unqualified_name) return unqualified_name->lastToken(); - else if (nested_name_specifier) - return nested_name_specifier->lastToken(); - return global_scope_token + 1; + + for (NestedNameSpecifierAST *it = nested_name_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (global_scope_token) + return global_scope_token + 1; + + return 0; } void ReferenceAST::accept0(ASTVisitor *visitor) From b46d8faf29b8503f2ed029d7260838e4c75c9a7f Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:45:56 +0100 Subject: [PATCH 155/230] Start with own undo/redo without depending on QTextEdit/QPlainTextEdit's undo/redo. --- src/plugins/fakevim/handler.cpp | 116 +++++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 15 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 5d26971f8a5..2c55c06772c 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -102,6 +102,14 @@ enum SubSubMode static const QString ConfigStartOfLine = "startofline"; static const QString ConfigOn = "on"; +struct EditOperation +{ + enum EditType { EditInsert, EditRemove } m_type; + int m_position; + int m_length; + QString m_data; +}; + class FakeVimHandler::Private { public: @@ -167,9 +175,6 @@ public: QString m_mvcount; QString m_opcount; - QStack m_undoStack; - QStack m_redoStack; - bool m_fakeEnd; QWidget *editor(); @@ -185,6 +190,14 @@ public: bool m_lastSearchForward; QString m_lastInsertion; + // undo handling + void recordInsert(int position, const QString &data); + void recordRemove(int position, int length); + void undo(); + void redo(); + QStack m_undoStack; + QStack m_redoStack; + // extra data for '.' QString m_dotCount; QString m_dotCommand; @@ -433,11 +446,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'a') { m_mode = InsertMode; m_lastInsertion.clear(); - m_tc.beginEditBlock(); + ///m_tc.beginEditBlock(); m_tc.movePosition(Right, MoveAnchor, 1); } else if (key == 'A') { m_mode = InsertMode; - m_tc.beginEditBlock(); + ///m_tc.beginEditBlock(); m_tc.movePosition(EndOfLine, MoveAnchor); m_lastInsertion.clear(); } else if (key == 'b') { @@ -448,7 +461,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key == 'c') { m_submode = ChangeSubMode; - m_tc.beginEditBlock(); + ///m_tc.beginEditBlock(); } else if (key == 'C') { m_submode = ChangeSubMode; //m_tc.beginEditBlock(); @@ -501,7 +514,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key == 'i') { m_mode = InsertMode; - //m_tc.beginEditBlock(); + ///m_tc.beginEditBlock(); m_lastInsertion.clear(); } else if (key == 'I') { m_mode = InsertMode; @@ -510,13 +523,13 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) else moveToFirstNonBlankOnLine(); m_tc.clearSelection(); - //m_tc.beginEditBlock(); + ///m_tc.beginEditBlock(); m_lastInsertion.clear(); } else if (key == 'j' || key == Key_Down) { m_tc.movePosition(Down, KeepAnchor, count()); finishMovement(); } else if (key == 'J') { - m_tc.beginEditBlock(); + ///m_tc.beginEditBlock(); if (m_submode == NoSubMode) { for (int i = qMax(count(), 2) - 1; --i >= 0; ) { m_tc.movePosition(EndOfLine); @@ -527,7 +540,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) if (!m_gflag) m_tc.movePosition(Left, MoveAnchor, 1); } - m_tc.endEditBlock(); + ///m_tc.endEditBlock(); } else if (key == 'k' || key == Key_Up) { m_tc.movePosition(Up, KeepAnchor, count()); finishMovement(); @@ -576,7 +589,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_tc.movePosition(Left); } } else if (key == control('r')) { - EDITOR(redo()); + redo(); } else if (key == 's') { m_submode = ChangeSubMode; //m_tc.beginEditBlock(); @@ -585,7 +598,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_subsubmode = FtSubSubMode; m_subsubdata = key; } else if (key == 'u') { - EDITOR(undo()); + undo(); } else if (key == 'V') { enterVisualLineMode(); } else if (key == 'w') { @@ -638,11 +651,17 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) { if (key == Key_Escape) { - for (int i = 1; i < count(); ++i) + // start with '1', as one instance was already physically inserted + // while typing + QString data = m_lastInsertion; + for (int i = 1; i < count(); ++i) { m_tc.insertText(m_lastInsertion); + data += m_lastInsertion; + } + recordInsert(m_tc.position() - m_lastInsertion.size(), data); m_tc.movePosition(Left, MoveAnchor, qMin(1, leftDist())); m_mode = CommandMode; - m_tc.endEditBlock(); + ///m_tc.endEditBlock(); } else if (key == Key_Left) { m_tc.movePosition(Left, MoveAnchor, 1); m_lastInsertion.clear(); @@ -657,7 +676,7 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) m_lastInsertion.clear(); } else if (key == Key_Return) { m_tc.insertBlock(); - m_lastInsertion.clear(); + m_lastInsertion += "\n"; } else if (key == Key_Backspace) { m_tc.deletePreviousChar(); m_lastInsertion = m_lastInsertion.left(m_lastInsertion.size() - 1); @@ -1109,6 +1128,73 @@ QWidget *FakeVimHandler::Private::editor() : static_cast(m_plaintextedit); } +void FakeVimHandler::Private::undo() +{ +#if 0 + EDITOR(undo()); +#else + if (m_undoStack.isEmpty()) + return; + EditOperation op = m_undoStack.pop(); + QTextCursor tc = m_tc; + tc.setPosition(op.m_position, MoveAnchor); + if (op.m_type == EditOperation::EditInsert) { + tc.setPosition(op.m_position + op.m_length, KeepAnchor); + tc.deleteChar(); + } else { + tc.insertText(op.m_data); + } + m_redoStack.push(op); +#endif +} + +void FakeVimHandler::Private::redo() +{ +#if 0 + EDITOR(redo()); +#else + if (m_redoStack.isEmpty()) + return; + EditOperation op = m_redoStack.pop(); + QTextCursor tc = m_tc; + tc.setPosition(op.m_position, MoveAnchor); + if (op.m_type == EditOperation::EditInsert) { + tc.insertText(op.m_data); + } else { + tc.setPosition(op.m_position + op.m_length, KeepAnchor); + tc.deleteChar(); + } + m_undoStack.push(op); +#endif +} + +void FakeVimHandler::Private::recordInsert(int position, const QString &data) +{ + qDebug() << "INSERT AT " << position << " DATA: " << data; + EditOperation op; + op.m_type = EditOperation::EditInsert; + op.m_position = position; + op.m_length = data.size(); + op.m_data = data; + m_undoStack.push(op); + m_redoStack.clear(); +} + +void FakeVimHandler::Private::recordRemove(int position, int length) +{ + qDebug() << "REMOVE AT " << position << " LEN: " << length; + QTextCursor tc = m_tc; + tc.setPosition(position, MoveAnchor); + tc.setPosition(position + length, KeepAnchor); + EditOperation op; + op.m_type = EditOperation::EditRemove; + op.m_position = position; + op.m_length = length; + op.m_data = tc.selection().toPlainText(); + m_undoStack.push(op); + m_redoStack.clear(); +} + /////////////////////////////////////////////////////////////////////// // // FakeVimHandler From 2f1e09ccc5632fd61cce60a15aa369b5f3904538 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:48:55 +0100 Subject: [PATCH 156/230] progress on homegrown undo/redo --- src/plugins/fakevim/handler.cpp | 90 ++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 35 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 2c55c06772c..ef55fb5725c 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -104,12 +104,24 @@ static const QString ConfigOn = "on"; struct EditOperation { - enum EditType { EditInsert, EditRemove } m_type; + EditOperation() : m_position(-1), m_itemCount(0) {} int m_position; - int m_length; - QString m_data; + int m_itemCount; // used to combine several operations + QString m_from; + QString m_to; }; +QDebug &operator<<(QDebug &ts, const EditOperation &op) +{ + if (op.m_itemCount > 0) { + ts << "EDIT BLOCK WITH" << op.m_itemCount << "ITEMS"; + } else { + ts << "EDIT AT " << op.m_position + << " FROM " << op.m_from << " TO " << op.m_to; + } + return ts; +} + class FakeVimHandler::Private { public: @@ -192,6 +204,7 @@ public: // undo handling void recordInsert(int position, const QString &data); + void recordRemove(int position, const QString &data); void recordRemove(int position, int length); void undo(); void redo(); @@ -281,6 +294,8 @@ bool FakeVimHandler::Private::eventFilter(QObject *ob, QEvent *ev) void FakeVimHandler::Private::handleKey(int key, const QString &text) { + //qDebug() << "KEY: " << key << text << "POS: " << m_tc.position(); + //qDebug() << "\nUNDO: " << m_undoStack << "\nREDO: " << m_redoStack; if (m_mode == InsertMode) handleInsertMode(key, text); else if (m_mode == CommandMode) @@ -301,6 +316,7 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand) } else if (m_submode == DeleteSubMode) { if (!dotCommand.isEmpty()) m_dotCommand = "d" + dotCommand; + recordRemove(qMin(m_tc.position(), m_tc.anchor()), m_tc.selectedText()); m_registers[m_register] = m_tc.selectedText(); m_tc.removeSelectedText(); m_submode = NoSubMode; @@ -446,11 +462,9 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'a') { m_mode = InsertMode; m_lastInsertion.clear(); - ///m_tc.beginEditBlock(); m_tc.movePosition(Right, MoveAnchor, 1); } else if (key == 'A') { m_mode = InsertMode; - ///m_tc.beginEditBlock(); m_tc.movePosition(EndOfLine, MoveAnchor); m_lastInsertion.clear(); } else if (key == 'b') { @@ -461,10 +475,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key == 'c') { m_submode = ChangeSubMode; - ///m_tc.beginEditBlock(); } else if (key == 'C') { m_submode = ChangeSubMode; - //m_tc.beginEditBlock(); m_tc.movePosition(EndOfLine, KeepAnchor); finishMovement(); } else if (key == 'd' && m_visualLineMode) { @@ -514,7 +526,6 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) finishMovement(); } else if (key == 'i') { m_mode = InsertMode; - ///m_tc.beginEditBlock(); m_lastInsertion.clear(); } else if (key == 'I') { m_mode = InsertMode; @@ -523,13 +534,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) else moveToFirstNonBlankOnLine(); m_tc.clearSelection(); - ///m_tc.beginEditBlock(); m_lastInsertion.clear(); } else if (key == 'j' || key == Key_Down) { m_tc.movePosition(Down, KeepAnchor, count()); finishMovement(); } else if (key == 'J') { - ///m_tc.beginEditBlock(); + EditOperation op; if (m_submode == NoSubMode) { for (int i = qMax(count(), 2) - 1; --i >= 0; ) { m_tc.movePosition(EndOfLine); @@ -540,7 +550,6 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) if (!m_gflag) m_tc.movePosition(Left, MoveAnchor, 1); } - ///m_tc.endEditBlock(); } else if (key == 'k' || key == Key_Up) { m_tc.movePosition(Up, KeepAnchor, count()); finishMovement(); @@ -565,13 +574,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'o') { m_mode = InsertMode; m_lastInsertion.clear(); - //m_tc.beginEditBlock(); // FIXME: unusable due to drawing errors m_tc.movePosition(EndOfLine, MoveAnchor); m_tc.insertText("\n"); } else if (key == 'O') { m_mode = InsertMode; m_lastInsertion.clear(); - //m_tc.beginEditBlock(); // FIXME: unusable due to drawing errors m_tc.movePosition(StartOfLine, MoveAnchor); m_tc.movePosition(Left, MoveAnchor, 1); m_tc.insertText("\n"); @@ -592,7 +599,6 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) redo(); } else if (key == 's') { m_submode = ChangeSubMode; - //m_tc.beginEditBlock(); m_tc.movePosition(Right, KeepAnchor, qMin(count(), rightDist())); } else if (key == 't' || key == 'T') { m_subsubmode = FtSubSubMode; @@ -661,7 +667,6 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) recordInsert(m_tc.position() - m_lastInsertion.size(), data); m_tc.movePosition(Left, MoveAnchor, qMin(1, leftDist())); m_mode = CommandMode; - ///m_tc.endEditBlock(); } else if (key == Key_Left) { m_tc.movePosition(Left, MoveAnchor, 1); m_lastInsertion.clear(); @@ -1136,13 +1141,20 @@ void FakeVimHandler::Private::undo() if (m_undoStack.isEmpty()) return; EditOperation op = m_undoStack.pop(); - QTextCursor tc = m_tc; - tc.setPosition(op.m_position, MoveAnchor); - if (op.m_type == EditOperation::EditInsert) { - tc.setPosition(op.m_position + op.m_length, KeepAnchor); - tc.deleteChar(); + //qDebug() << "UNDO " << op; + if (op.m_itemCount > 0) { + for (int i = op.m_itemCount; --i >= 0; ) + undo(); } else { - tc.insertText(op.m_data); + //QTextCursor tc = m_tc; + m_tc.setPosition(op.m_position, MoveAnchor); + if (!op.m_to.isEmpty()) { + m_tc.setPosition(op.m_position + op.m_to.size(), KeepAnchor); + m_tc.deleteChar(); + } + if (!op.m_from.isEmpty()) + m_tc.insertText(op.m_from); + m_tc.setPosition(op.m_position, MoveAnchor); } m_redoStack.push(op); #endif @@ -1156,13 +1168,20 @@ void FakeVimHandler::Private::redo() if (m_redoStack.isEmpty()) return; EditOperation op = m_redoStack.pop(); - QTextCursor tc = m_tc; - tc.setPosition(op.m_position, MoveAnchor); - if (op.m_type == EditOperation::EditInsert) { - tc.insertText(op.m_data); + //qDebug() << "REDO " << op; + if (op.m_itemCount > 0) { + for (int i = op.m_itemCount; --i >= 0; ) + undo(); } else { - tc.setPosition(op.m_position + op.m_length, KeepAnchor); - tc.deleteChar(); + int pos = op.m_position; // - op.m_to.size() + op.m_from.size(); + m_tc.setPosition(pos, MoveAnchor); + if (!op.m_from.isEmpty()) { + m_tc.setPosition(pos + op.m_from.size(), KeepAnchor); + m_tc.deleteChar(); + } + if (!op.m_to.isEmpty()) + m_tc.insertText(op.m_to); + m_tc.setPosition(pos, MoveAnchor); } m_undoStack.push(op); #endif @@ -1170,29 +1189,30 @@ void FakeVimHandler::Private::redo() void FakeVimHandler::Private::recordInsert(int position, const QString &data) { - qDebug() << "INSERT AT " << position << " DATA: " << data; EditOperation op; - op.m_type = EditOperation::EditInsert; op.m_position = position; - op.m_length = data.size(); - op.m_data = data; + op.m_to = data; m_undoStack.push(op); m_redoStack.clear(); + qDebug() << "INSERT " << op; } void FakeVimHandler::Private::recordRemove(int position, int length) { - qDebug() << "REMOVE AT " << position << " LEN: " << length; QTextCursor tc = m_tc; tc.setPosition(position, MoveAnchor); tc.setPosition(position + length, KeepAnchor); + recordRemove(position, tc.selection().toPlainText()); +} + +void FakeVimHandler::Private::recordRemove(int position, const QString &data) +{ EditOperation op; - op.m_type = EditOperation::EditRemove; op.m_position = position; - op.m_length = length; - op.m_data = tc.selection().toPlainText(); + op.m_from = data; m_undoStack.push(op); m_redoStack.clear(); + qDebug() << "REMOVE " << op; } /////////////////////////////////////////////////////////////////////// From 2584bb928cacdb2e1947452b06e989819e538e63 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:49:33 +0100 Subject: [PATCH 157/230] fix missing status line updates in insert mode --- src/plugins/fakevim/handler.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index ef55fb5725c..89d403e2386 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -340,7 +340,9 @@ void FakeVimHandler::Private::updateMiniBuffer() msg = m_currentMessage; m_currentMessage.clear(); } else if (m_visualLineMode) { - msg = "-- VISUAL LINE--"; + msg = "-- VISUAL LINE --"; + } else if (m_mode == InsertMode) { + msg = "-- INSERT --"; } else { msg = QChar(m_commandCode ? m_commandCode : ' '); for (int i = 0; i != m_commandBuffer.size(); ++i) { @@ -463,6 +465,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_mode = InsertMode; m_lastInsertion.clear(); m_tc.movePosition(Right, MoveAnchor, 1); + updateMiniBuffer(); } else if (key == 'A') { m_mode = InsertMode; m_tc.movePosition(EndOfLine, MoveAnchor); @@ -527,6 +530,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'i') { m_mode = InsertMode; m_lastInsertion.clear(); + updateMiniBuffer(); } else if (key == 'I') { m_mode = InsertMode; if (m_gflag) @@ -701,7 +705,8 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) } else { m_lastInsertion.append(text); m_tc.insertText(text); - } + } + updateMiniBuffer(); } void FakeVimHandler::Private::handleExMode(int key, const QString &text) From 69475d708d613817bba8a3018f027ceb2523a557 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:50:30 +0100 Subject: [PATCH 158/230] add status line feedback for :r --- src/plugins/fakevim/handler.cpp | 38 ++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 89d403e2386..193c0ce94fa 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -189,7 +189,7 @@ public: bool m_fakeEnd; - QWidget *editor(); + QWidget *editor() const; bool isSearchCommand() const { return m_commandCode == '?' || m_commandCode == '/'; } int m_commandCode; // ?, /, : ... @@ -333,8 +333,6 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand) void FakeVimHandler::Private::updateMiniBuffer() { - if (m_tc.isNull()) - return; QString msg; if (!m_currentMessage.isEmpty()) { msg = m_currentMessage; @@ -355,6 +353,7 @@ void FakeVimHandler::Private::updateMiniBuffer() } } } + int L = linesInDocument(); int l = cursorLineInDocument(); int w = columnsOnScreen(); msg += QString(w, ' '); @@ -362,8 +361,7 @@ void FakeVimHandler::Private::updateMiniBuffer() QString pos = tr("%1,%2").arg(l + 1).arg(cursorColumnInDocument() + 1); msg += tr("%1").arg(pos, -12); // FIXME: physical "-" logical - msg += tr("%1").arg(l * 100 / (m_tc.document()->blockCount() - 1), 4); - msg += '%'; + msg += L ? tr("%1%%").arg(l * 100 / L, 4) : QString("All"); emit q->commandBufferChanged(msg); } @@ -429,6 +427,7 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == ':' || key == '/' || key == '?') { m_commandCode = key; m_mode = ExMode; + m_commandBuffer.clear(); if (isSearchCommand()) { m_searchHistory.append(QString()); m_searchHistoryIndex = m_searchHistory.size() - 1; @@ -900,13 +899,16 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) .arg(fileName).arg(exists ? " " : " [New] ") .arg(ba.count('\n')).arg(ba.size())); } - } else if (cmd.startsWith("r ")) { + } else if (cmd.startsWith("r ")) { // :r m_currentFileName = cmd.mid(2); QFile file(m_currentFileName); file.open(QIODevice::ReadOnly); QTextStream ts(&file); - EDITOR(setPlainText(ts.readAll())); - showMessage(QString()); + QString data = ts.readAll(); + EDITOR(setPlainText(data)); + m_commandBuffer = QString("\"%1\" %2L, %3C") + .arg(m_currentFileName).arg(data.count('\n')).arg(data.size()); + updateMiniBuffer(); } else { showMessage("E492: Not an editor command: " + cmd0); } @@ -1056,18 +1058,24 @@ void FakeVimHandler::Private::moveToNextWord(bool simple) int FakeVimHandler::Private::cursorLineOnScreen() const { + if (!editor()) + return 0; QRect rect = EDITOR(cursorRect()); return rect.y() / rect.height(); } int FakeVimHandler::Private::linesOnScreen() const { + if (!editor()) + return 1; QRect rect = EDITOR(cursorRect()); return EDITOR(height()) / rect.height(); } int FakeVimHandler::Private::columnsOnScreen() const { + if (!editor()) + return 1; QRect rect = EDITOR(cursorRect()); return EDITOR(width()) / rect.width(); } @@ -1131,7 +1139,7 @@ void FakeVimHandler::Private::leaveVisualLineMode() updateMiniBuffer(); } -QWidget *FakeVimHandler::Private::editor() +QWidget *FakeVimHandler::Private::editor() const { return m_textedit ? static_cast(m_textedit) @@ -1151,7 +1159,6 @@ void FakeVimHandler::Private::undo() for (int i = op.m_itemCount; --i >= 0; ) undo(); } else { - //QTextCursor tc = m_tc; m_tc.setPosition(op.m_position, MoveAnchor); if (!op.m_to.isEmpty()) { m_tc.setPosition(op.m_position + op.m_to.size(), KeepAnchor); @@ -1176,17 +1183,16 @@ void FakeVimHandler::Private::redo() //qDebug() << "REDO " << op; if (op.m_itemCount > 0) { for (int i = op.m_itemCount; --i >= 0; ) - undo(); + redo(); } else { - int pos = op.m_position; // - op.m_to.size() + op.m_from.size(); - m_tc.setPosition(pos, MoveAnchor); + m_tc.setPosition(op.m_position, MoveAnchor); if (!op.m_from.isEmpty()) { - m_tc.setPosition(pos + op.m_from.size(), KeepAnchor); + m_tc.setPosition(op.m_position + op.m_from.size(), KeepAnchor); m_tc.deleteChar(); } if (!op.m_to.isEmpty()) m_tc.insertText(op.m_to); - m_tc.setPosition(pos, MoveAnchor); + m_tc.setPosition(op.m_position, MoveAnchor); } m_undoStack.push(op); #endif @@ -1199,7 +1205,6 @@ void FakeVimHandler::Private::recordInsert(int position, const QString &data) op.m_to = data; m_undoStack.push(op); m_redoStack.clear(); - qDebug() << "INSERT " << op; } void FakeVimHandler::Private::recordRemove(int position, int length) @@ -1217,7 +1222,6 @@ void FakeVimHandler::Private::recordRemove(int position, const QString &data) op.m_from = data; m_undoStack.push(op); m_redoStack.clear(); - qDebug() << "REMOVE " << op; } /////////////////////////////////////////////////////////////////////// From d90dc9e3f20e0b4eb8e8865044c3b94dc7608945 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:51:03 +0100 Subject: [PATCH 159/230] work on command line display --- src/plugins/fakevim/handler.cpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 193c0ce94fa..4facddabdff 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -343,8 +343,7 @@ void FakeVimHandler::Private::updateMiniBuffer() msg = "-- INSERT --"; } else { msg = QChar(m_commandCode ? m_commandCode : ' '); - for (int i = 0; i != m_commandBuffer.size(); ++i) { - QChar c = m_commandBuffer.at(i); + foreach (QChar c, m_commandBuffer) { if (c.unicode() < 32) { msg += '^'; msg += QChar(c.unicode() + 64); @@ -352,16 +351,24 @@ void FakeVimHandler::Private::updateMiniBuffer() msg += c; } } + msg += " "; } - int L = linesInDocument(); + int linesInDoc = linesInDocument(); int l = cursorLineInDocument(); int w = columnsOnScreen(); + if (msg.size() > w - 20) + msg = ">" + msg.right(w - 19); msg += QString(w, ' '); - msg = msg.left(w - 20); + msg = msg.left(w - 19); QString pos = tr("%1,%2").arg(l + 1).arg(cursorColumnInDocument() + 1); - msg += tr("%1").arg(pos, -12); + msg += tr("%1").arg(pos, -10); // FIXME: physical "-" logical - msg += L ? tr("%1%%").arg(l * 100 / L, 4) : QString("All"); + if (linesInDoc != 0) { + msg += tr("%1").arg(l * 100 / linesInDoc, 4); + msg += "%"; + } else { + msg += "All"; + } emit q->commandBufferChanged(msg); } @@ -895,9 +902,10 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) file.close(); file.open(QIODevice::ReadWrite); QByteArray ba = file.readAll(); - showMessage(tr("\"%1\" %2 %3L, %4C written") + m_commandBuffer = QString("\"%1\" %2 %3L, %4C written") .arg(fileName).arg(exists ? " " : " [New] ") - .arg(ba.count('\n')).arg(ba.size())); + .arg(ba.count('\n')).arg(ba.size()); + updateMiniBuffer(); } } else if (cmd.startsWith("r ")) { // :r m_currentFileName = cmd.mid(2); From 2d7c5de370f157887c0644bbabdbec9ecc688a0a Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:51:24 +0100 Subject: [PATCH 160/230] more status line work --- src/plugins/fakevim/handler.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 4facddabdff..b51851cd3c3 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -167,7 +167,7 @@ public: void moveToNextWord(bool simple); void moveToWordBoundary(bool simple, bool forward); void handleFfTt(int key); - void handleCommand(const QString &cmd); + void handleExCommand(const QString &cmd); // helper function for handleCommand. return 1 based line index. int readLineCode(QString &cmd); @@ -734,8 +734,7 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) if (!m_commandBuffer.isEmpty()) { m_commandHistory.takeLast(); m_commandHistory.append(m_commandBuffer); - handleCommand(m_commandBuffer); - m_commandBuffer.clear(); + handleExCommand(m_commandBuffer); m_commandCode = 0; } m_mode = CommandMode; @@ -745,7 +744,6 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_searchHistory.append(m_commandBuffer); m_lastSearchForward = (m_commandCode == '/'); search(lastSearchString(), m_lastSearchForward); - m_commandBuffer.clear(); m_commandCode = 0; } m_mode = CommandMode; @@ -839,7 +837,7 @@ QTextCursor FakeVimHandler::Private::selectRange(int beginLine, int endLine) return tc; } -void FakeVimHandler::Private::handleCommand(const QString &cmd0) +void FakeVimHandler::Private::handleExCommand(const QString &cmd0) { QString cmd = cmd0; if (cmd.startsWith("%")) @@ -850,6 +848,7 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) int line = readLineCode(cmd); if (line != -1) + m_mode = CommandMode; beginLine = line; if (cmd.startsWith(',')) { @@ -881,6 +880,7 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) m_registers[reg.at(0).unicode()] = tc.selection().toPlainText(); tc.removeSelectedText(); } else if (reWrite.indexIn(cmd) != -1) { // :w + bool noArgs = (beginLine == -1); if (beginLine == -1) beginLine = 0; if (endLine == -1) @@ -891,7 +891,7 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) fileName = m_currentFileName; QFile file(fileName); bool exists = file.exists(); - if (exists && !forced) { + if (exists && !forced && !noArgs) { showMessage("E13: File exists (add ! to override)"); } else { file.open(QIODevice::ReadWrite); @@ -905,6 +905,7 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) m_commandBuffer = QString("\"%1\" %2 %3L, %4C written") .arg(fileName).arg(exists ? " " : " [New] ") .arg(ba.count('\n')).arg(ba.size()); + m_mode = CommandMode; updateMiniBuffer(); } } else if (cmd.startsWith("r ")) { // :r @@ -916,6 +917,7 @@ void FakeVimHandler::Private::handleCommand(const QString &cmd0) EDITOR(setPlainText(data)); m_commandBuffer = QString("\"%1\" %2L, %3C") .arg(m_currentFileName).arg(data.count('\n')).arg(data.size()); + m_mode = CommandMode; updateMiniBuffer(); } else { showMessage("E492: Not an editor command: " + cmd0); @@ -1281,6 +1283,6 @@ void FakeVimHandler::handleCommand(QWidget *widget, const QString &cmd) { d->m_textedit = qobject_cast(widget); d->m_plaintextedit = qobject_cast(widget); - d->handleCommand(cmd); + d->handleExCommand(cmd); } From 8c23bb3cf7f9cd8aa61ae999c84ef2eaaf6eb089 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:52:05 +0100 Subject: [PATCH 161/230] some visual feedback for visual line mode --- src/plugins/fakevim/handler.cpp | 100 +++++++++++++++++++++++++------- 1 file changed, 78 insertions(+), 22 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index b51851cd3c3..31672c1ec98 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -99,6 +99,14 @@ enum SubSubMode TickSubSubMode // used for ' }; +enum VisualMode +{ + NoVisualMode, + VisualCharMode, + VisualLineMode, + VisualBlockMode, +}; + static const QString ConfigStartOfLine = "startofline"; static const QString ConfigOn = "on"; @@ -128,7 +136,9 @@ public: Private(FakeVimHandler *parent); bool eventFilter(QObject *ob, QEvent *ev); + void handleExCommand(const QString &cmd); +private: static int shift(int key) { return key + 32; } static int control(int key) { return key + 256; } @@ -140,6 +150,7 @@ public: void handleExMode(int key, const QString &text); void finishMovement(const QString &text = QString()); void updateMiniBuffer(); + void updateSelection(); void search(const QString &needle, bool forward); void showMessage(const QString &msg); @@ -167,20 +178,22 @@ public: void moveToNextWord(bool simple); void moveToWordBoundary(bool simple, bool forward); void handleFfTt(int key); - void handleExCommand(const QString &cmd); // helper function for handleCommand. return 1 based line index. int readLineCode(QString &cmd); QTextCursor selectRange(int beginLine, int endLine); +public: + QTextEdit *m_textedit; + QPlainTextEdit *m_plaintextedit; + +private: FakeVimHandler *q; Mode m_mode; SubMode m_submode; SubSubMode m_subsubmode; int m_subsubdata; QString m_input; - QTextEdit *m_textedit; - QPlainTextEdit *m_plaintextedit; QTextCursor m_tc; QHash m_registers; int m_register; @@ -225,9 +238,9 @@ public: int m_commandHistoryIndex; // visual line mode - void enterVisualLineMode(); - void leaveVisualLineMode(); - bool m_visualLineMode; + void enterVisualMode(VisualMode visualMode); + void leaveVisualMode(); + VisualMode m_visualMode; // marks as lines QHash m_marks; @@ -250,7 +263,7 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) m_gflag = false; m_textedit = 0; m_plaintextedit = 0; - m_visualLineMode = false; + m_visualMode = NoVisualMode; m_config[ConfigStartOfLine] = ConfigOn; } @@ -328,17 +341,56 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand) m_gflag = false; m_register = '"'; m_tc.clearSelection(); + + updateSelection(); updateMiniBuffer(); } +void FakeVimHandler::Private::updateSelection() +{ + QList selections; + if (m_visualMode != NoVisualMode) { + QTextEdit::ExtraSelection sel; + sel.cursor = m_tc; + sel.format = m_tc.blockCharFormat(); + sel.format.setFontWeight(QFont::Bold); + sel.format.setFontUnderline(true); + int pos = m_tc.position(); + int anchor = m_marks['<']; + //qDebug() << "POS: " << pos << " ANCHOR: " << anchor; + if (m_visualMode == VisualCharMode) { + sel.cursor.setPosition(anchor, KeepAnchor); + selections.append(sel); + } else if (m_visualMode == VisualLineMode) { + sel.cursor.setPosition(qMin(pos, anchor), MoveAnchor); + sel.cursor.movePosition(StartOfLine, MoveAnchor); + sel.cursor.setPosition(qMax(pos, anchor), KeepAnchor); + sel.cursor.movePosition(EndOfLine, KeepAnchor); + selections.append(sel); + } else if (m_visualMode == VisualBlockMode) { + // FIXME: This shows lines right now... + sel.cursor.setPosition(qMin(pos, anchor), MoveAnchor); + sel.cursor.movePosition(StartOfLine, MoveAnchor); + sel.cursor.setPosition(qMax(pos, anchor), KeepAnchor); + sel.cursor.movePosition(EndOfLine, KeepAnchor); + selections.append(sel); + } + } + EDITOR(setExtraSelections(selections)); +} + void FakeVimHandler::Private::updateMiniBuffer() { QString msg; if (!m_currentMessage.isEmpty()) { msg = m_currentMessage; m_currentMessage.clear(); - } else if (m_visualLineMode) { + } else if (m_visualMode == VisualCharMode) { + msg = "-- VISUAL --"; + } else if (m_visualMode == VisualLineMode) { msg = "-- VISUAL LINE --"; + } else if (m_visualMode == VisualBlockMode) { + msg = "-- VISUAL BLOCK --"; } else if (m_mode == InsertMode) { msg = "-- INSERT --"; } else { @@ -488,18 +540,18 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_submode = ChangeSubMode; m_tc.movePosition(EndOfLine, KeepAnchor); finishMovement(); - } else if (key == 'd' && m_visualLineMode) { - leaveVisualLineMode(); - int beginLine = lineForPosition(m_marks['<']); - int endLine = lineForPosition(m_marks['>']); - m_tc = selectRange(beginLine, endLine); - m_tc.removeSelectedText(); - } else if (key == 'd') { + } else if (key == 'd' && m_visualMode == NoVisualMode) { if (atEol()) m_tc.movePosition(Left, MoveAnchor, 1); m_opcount = m_mvcount; m_mvcount.clear(); m_submode = DeleteSubMode; + } else if (key == 'd') { + leaveVisualMode(); + int beginLine = lineForPosition(m_marks['<']); + int endLine = lineForPosition(m_marks['>']); + m_tc = selectRange(beginLine, endLine); + m_tc.removeSelectedText(); } else if (key == 'D') { m_submode = DeleteSubMode; m_tc.movePosition(Down, KeepAnchor, qMax(count() - 1, 0)); @@ -615,8 +667,12 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) m_subsubdata = key; } else if (key == 'u') { undo(); + } else if (key == 'v') { + enterVisualMode(VisualCharMode); } else if (key == 'V') { - enterVisualLineMode(); + enterVisualMode(VisualLineMode); + } else if (key == control('v')) { + enterVisualMode(VisualBlockMode); } else if (key == 'w') { moveToNextWord(false); finishMovement("w"); @@ -657,8 +713,8 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == Key_Delete) { m_tc.deleteChar(); } else if (key == Key_Escape) { - if (m_visualLineMode) - leaveVisualLineMode(); + if (m_visualMode != NoVisualMode) + leaveVisualMode(); } else { qDebug() << "Ignored" << key << text; } @@ -1135,16 +1191,16 @@ int FakeVimHandler::Private::lineForPosition(int pos) const return tc.block().blockNumber() + 1; } -void FakeVimHandler::Private::enterVisualLineMode() +void FakeVimHandler::Private::enterVisualMode(VisualMode visualMode) { - m_visualLineMode = true; + m_visualMode = visualMode; m_marks['<'] = m_tc.position(); updateMiniBuffer(); } -void FakeVimHandler::Private::leaveVisualLineMode() +void FakeVimHandler::Private::leaveVisualMode() { - m_visualLineMode = false; + m_visualMode = NoVisualMode; m_marks['>'] = m_tc.position(); updateMiniBuffer(); } From a387eed44c95be949bd2f9c6d3b2c31ffa139ff7 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 11:52:40 +0100 Subject: [PATCH 162/230] visual feedback for block selection. othewise block selection still does not work.. --- src/plugins/fakevim/handler.cpp | 41 +++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index 31672c1ec98..de1c5a6d2f6 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -355,25 +355,40 @@ void FakeVimHandler::Private::updateSelection() sel.format = m_tc.blockCharFormat(); sel.format.setFontWeight(QFont::Bold); sel.format.setFontUnderline(true); - int pos = m_tc.position(); - int anchor = m_marks['<']; - //qDebug() << "POS: " << pos << " ANCHOR: " << anchor; + int cursorPos = m_tc.position(); + int anchorPos = m_marks['<']; + //qDebug() << "POS: " << cursorPos << " ANCHOR: " << anchorPos; if (m_visualMode == VisualCharMode) { - sel.cursor.setPosition(anchor, KeepAnchor); + sel.cursor.setPosition(anchorPos, KeepAnchor); selections.append(sel); } else if (m_visualMode == VisualLineMode) { - sel.cursor.setPosition(qMin(pos, anchor), MoveAnchor); + sel.cursor.setPosition(qMin(cursorPos, anchorPos), MoveAnchor); sel.cursor.movePosition(StartOfLine, MoveAnchor); - sel.cursor.setPosition(qMax(pos, anchor), KeepAnchor); + sel.cursor.setPosition(qMax(cursorPos, anchorPos), KeepAnchor); sel.cursor.movePosition(EndOfLine, KeepAnchor); selections.append(sel); } else if (m_visualMode == VisualBlockMode) { - // FIXME: This shows lines right now... - sel.cursor.setPosition(qMin(pos, anchor), MoveAnchor); - sel.cursor.movePosition(StartOfLine, MoveAnchor); - sel.cursor.setPosition(qMax(pos, anchor), KeepAnchor); - sel.cursor.movePosition(EndOfLine, KeepAnchor); - selections.append(sel); + QTextCursor tc = m_tc; + tc.setPosition(anchorPos); + tc.movePosition(StartOfLine, MoveAnchor); + QTextBlock anchorBlock = tc.block(); + QTextBlock cursorBlock = m_tc.block(); + int anchorColumn = anchorPos - anchorBlock.position(); + int cursorColumn = cursorPos - cursorBlock.position(); + int startColumn = qMin(anchorColumn, cursorColumn); + int endColumn = qMax(anchorColumn, cursorColumn); + int endPos = cursorBlock.position(); + while (tc.position() <= endPos) { + if (startColumn < tc.block().length() - 1) { + int last = qMin(tc.block().length() - 1, endColumn); + int len = last - startColumn + 1; + sel.cursor = tc; + sel.cursor.movePosition(Right, MoveAnchor, startColumn); + sel.cursor.movePosition(Right, KeepAnchor, len); + selections.append(sel); + } + tc.movePosition(Down, MoveAnchor, 1); + } } } EDITOR(setExtraSelections(selections)); @@ -1196,6 +1211,7 @@ void FakeVimHandler::Private::enterVisualMode(VisualMode visualMode) m_visualMode = visualMode; m_marks['<'] = m_tc.position(); updateMiniBuffer(); + updateSelection(); } void FakeVimHandler::Private::leaveVisualMode() @@ -1203,6 +1219,7 @@ void FakeVimHandler::Private::leaveVisualMode() m_visualMode = NoVisualMode; m_marks['>'] = m_tc.position(); updateMiniBuffer(); + updateSelection(); } QWidget *FakeVimHandler::Private::editor() const From 5ceea60c161a87b7d9ec5817c962e52040f752c3 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:48:39 +0100 Subject: [PATCH 163/230] SimpleDeclarationAST::lastToken(). --- shared/cplusplus/AST.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index b6ddde0c0eb..43423015398 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2184,7 +2184,6 @@ unsigned ReferenceAST::firstToken() const unsigned ReferenceAST::lastToken() const { - assert(0 && "review me"); return amp_token + 1; } @@ -2202,8 +2201,11 @@ unsigned ReturnStatementAST::firstToken() const unsigned ReturnStatementAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + else if (expression) + return expression->lastToken(); + return return_token + 1; } void SimpleDeclarationAST::accept0(ASTVisitor *visitor) @@ -2222,23 +2224,24 @@ unsigned SimpleDeclarationAST::firstToken() const return decl_specifier_seq->firstToken(); else if (declarators) return declarators->firstToken(); - else - return semicolon_token; + return semicolon_token; } unsigned SimpleDeclarationAST::lastToken() const { - assert(0 && "review me"); if (semicolon_token) return semicolon_token + 1; + for (DeclaratorListAST *it = declarators; it; it = it->next) { if (! it->next) return it->lastToken(); } + for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) { if (! it->next) return it->lastToken(); } + return 0; } From dc08c07de04fda61f7dca91d712ec1c5f1f842cb Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:51:30 +0100 Subject: [PATCH 164/230] SwitchStatementAST::lastToken(). --- shared/cplusplus/AST.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 43423015398..6663cbba5d5 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2258,7 +2258,6 @@ unsigned SimpleNameAST::firstToken() const unsigned SimpleNameAST::lastToken() const { - assert(0 && "review me"); return identifier_token + 1; } @@ -2275,7 +2274,6 @@ unsigned SimpleSpecifierAST::firstToken() const unsigned SimpleSpecifierAST::lastToken() const { - assert(0 && "review me"); return specifier_token + 1; } @@ -2293,7 +2291,6 @@ unsigned TypeofSpecifierAST::firstToken() const unsigned TypeofSpecifierAST::lastToken() const { - assert(0 && "review me"); if (expression) return expression->lastToken(); return typeof_token + 1; @@ -2313,7 +2310,6 @@ unsigned SizeofExpressionAST::firstToken() const unsigned SizeofExpressionAST::lastToken() const { - assert(0 && "review me"); if (expression) return expression->lastToken(); return sizeof_token + 1; @@ -2333,7 +2329,6 @@ unsigned StringLiteralAST::firstToken() const unsigned StringLiteralAST::lastToken() const { - assert(0 && "review me"); if (next) return next->lastToken(); return token + 1; @@ -2354,10 +2349,15 @@ unsigned SwitchStatementAST::firstToken() const unsigned SwitchStatementAST::lastToken() const { - assert(0 && "review me"); if (statement) return statement->lastToken(); - return rparen_token + 1; + else if (rparen_token) + return rparen_token + 1; + else if (condition) + return condition->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return switch_token + 1; } void TemplateArgumentListAST::accept0(ASTVisitor *visitor) From 9666488fbe46cdf3a9b834cfaa3a21d28b42aad2 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:52:58 +0100 Subject: [PATCH 165/230] TemplateArgumentListAST::lastToken(). --- shared/cplusplus/AST.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 6663cbba5d5..ad0c65c6c25 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2375,9 +2375,8 @@ unsigned TemplateArgumentListAST::firstToken() const unsigned TemplateArgumentListAST::lastToken() const { - assert(0 && "review me"); - for (const TemplateArgumentListAST *it = this; it; it = it->next) { - if (! it->next) + for (TemplateArgumentListAST *it = this; it; it = it->next) { + if (! it->next && it->template_argument) return it->template_argument->lastToken(); } return 0; From c187d71cb05a6f829e2fcecc3dbd57be58dc12a4 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:55:41 +0100 Subject: [PATCH 166/230] TemplateDeclarationAST::lastToken(). --- shared/cplusplus/AST.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index ad0c65c6c25..d30e6c14a13 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2375,7 +2375,7 @@ unsigned TemplateArgumentListAST::firstToken() const unsigned TemplateArgumentListAST::lastToken() const { - for (TemplateArgumentListAST *it = this; it; it = it->next) { + for (const TemplateArgumentListAST *it = this; it; it = it->next) { if (! it->next && it->template_argument) return it->template_argument->lastToken(); } @@ -2401,10 +2401,24 @@ unsigned TemplateDeclarationAST::firstToken() const unsigned TemplateDeclarationAST::lastToken() const { - assert(0 && "review me"); if (declaration) return declaration->lastToken(); - return greater_token + 1; + else if (greater_token) + return greater_token + 1; + + for (DeclarationAST *it = template_parameters; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (less_token) + return less_token + 1; + else if (template_token) + return template_token + 1; + else if (export_token) + return export_token + 1; + + return 0; } void TemplateIdAST::accept0(ASTVisitor *visitor) From 43db13a21fa35bd7e64503c1c1f6e7ca75c100e0 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:57:04 +0100 Subject: [PATCH 167/230] TemplateIdAST::lastToken(). --- shared/cplusplus/AST.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index d30e6c14a13..5921c4ae449 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2437,8 +2437,18 @@ unsigned TemplateIdAST::firstToken() const unsigned TemplateIdAST::lastToken() const { - assert(0 && "review me"); - return greater_token + 1; + if (greater_token) + return greater_token + 1; + + for (TemplateArgumentListAST *it = template_arguments; it; it = it->next) { + if (! it->next && it->template_argument) + return it->template_argument->lastToken(); + } + + if (less_token) + return less_token + 1; + + return identifier_token + 1; } void TemplateTypeParameterAST::accept0(ASTVisitor *visitor) From 0f3372118aa95acc2440ea2a44fb08a267091db1 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 11:59:28 +0100 Subject: [PATCH 168/230] TemplateTypeParameterAST::lastToken(). --- shared/cplusplus/AST.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 5921c4ae449..4ab7cdc4248 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2464,7 +2464,6 @@ unsigned TemplateTypeParameterAST::firstToken() const unsigned TemplateTypeParameterAST::lastToken() const { - assert(0 && "review me"); if (type_id) return type_id->lastToken(); else if (equal_token) @@ -2473,7 +2472,18 @@ unsigned TemplateTypeParameterAST::lastToken() const return name->lastToken(); else if (class_token) return class_token + 1; - return greater_token + 1; + else if (greater_token) + return greater_token + 1; + + for (DeclarationAST *it = template_parameters; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (less_token) + return less_token + 1; + + return template_token + 1; } void ThisExpressionAST::accept0(ASTVisitor *visitor) From 2fb5e63097dfb8b37896e71e0718d63844f64fc3 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:01:57 +0100 Subject: [PATCH 169/230] TypeConstructorCallAST::lastToken(). --- shared/cplusplus/AST.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 4ab7cdc4248..8cb625b4ad9 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2499,7 +2499,6 @@ unsigned ThisExpressionAST::firstToken() const unsigned ThisExpressionAST::lastToken() const { - assert(0 && "review me"); return this_token + 1; } @@ -2517,7 +2516,6 @@ unsigned ThrowExpressionAST::firstToken() const unsigned ThrowExpressionAST::lastToken() const { - assert(0 && "review me"); if (expression) return expression->lastToken(); return throw_token + 1; @@ -2539,7 +2537,6 @@ unsigned TranslationUnitAST::firstToken() const unsigned TranslationUnitAST::lastToken() const { - assert(0 && "review me"); for (DeclarationAST *it = declarations; it; it = it->next) { if (! it->next) return it->lastToken(); @@ -2562,13 +2559,14 @@ unsigned TryBlockStatementAST::firstToken() const unsigned TryBlockStatementAST::lastToken() const { - assert(0 && "review me"); for (CatchClauseAST *it = catch_clause_seq; it; it = it->next) { if (! it->next) return it->lastToken(); } + if (statement) return statement->lastToken(); + return try_token + 1; } @@ -2590,8 +2588,24 @@ unsigned TypeConstructorCallAST::firstToken() const unsigned TypeConstructorCallAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + + for (ExpressionListAST *it = expression_list; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (lparen_token) + return lparen_token + 1; + + + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return 0; } void TypeIdAST::accept0(ASTVisitor *visitor) From c1a2afceb5ef543138382817702feeca74e9cefb Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:02:54 +0100 Subject: [PATCH 170/230] TypeIdAST::lastToken(). --- shared/cplusplus/AST.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 8cb625b4ad9..67813b9e7d2 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2624,10 +2624,15 @@ unsigned TypeIdAST::firstToken() const unsigned TypeIdAST::lastToken() const { - assert(0 && "review me"); if (declarator) return declarator->lastToken(); - return type_specifier->lastToken(); + + for (SpecifierAST *it = type_specifier; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + return 0; } void TypeidExpressionAST::accept0(ASTVisitor *visitor) From 750b0417b030ad44a7864ed1ce23e563cf5d5633 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:04:05 +0100 Subject: [PATCH 171/230] TypeidExpressionAST::lastToken(). --- shared/cplusplus/AST.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 67813b9e7d2..215a754441e 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2649,8 +2649,14 @@ unsigned TypeidExpressionAST::firstToken() const unsigned TypeidExpressionAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + else if (expression) + return expression->lastToken(); + else if (lparen_token) + return lparen_token + 1; + + return typeid_token + 1; } void TypenameCallExpressionAST::accept0(ASTVisitor *visitor) From 1a7a8102d560dad5ed3ee098364047f9bfb1acfd Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:05:30 +0100 Subject: [PATCH 172/230] TypenameCallExpressionAST::lastToken(). --- shared/cplusplus/AST.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 215a754441e..e357fc249cf 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2676,8 +2676,20 @@ unsigned TypenameCallExpressionAST::firstToken() const unsigned TypenameCallExpressionAST::lastToken() const { - assert(0 && "review me"); - return rparen_token + 1; + if (rparen_token) + return rparen_token + 1; + + for (ExpressionListAST *it = expression_list; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + + if (lparen_token) + return lparen_token + 1; + else if (name) + return name->lastToken(); + + return typename_token + 1; } void TypenameTypeParameterAST::accept0(ASTVisitor *visitor) From 7d719a660ba7fbcb80a1086812e6408c6347bc3a Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:06:45 +0100 Subject: [PATCH 173/230] TypenameTypeParameterAST::lastToken(). --- shared/cplusplus/AST.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index e357fc249cf..7818d29f5c5 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2707,7 +2707,6 @@ unsigned TypenameTypeParameterAST::firstToken() const unsigned TypenameTypeParameterAST::lastToken() const { - assert(0 && "review me"); if (type_id) return type_id->lastToken(); else if (equal_token) From fa0ef5224bee70c950a26edc4dd07979f5d2d48f Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:07:55 +0100 Subject: [PATCH 174/230] UsingAST::lastToken(). --- shared/cplusplus/AST.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 7818d29f5c5..e0f1582db6d 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2730,7 +2730,6 @@ unsigned UnaryExpressionAST::firstToken() const unsigned UnaryExpressionAST::lastToken() const { - assert(0 && "review me"); if (expression) return expression->lastToken(); return unary_op_token + 1; @@ -2750,8 +2749,13 @@ unsigned UsingAST::firstToken() const unsigned UsingAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + else if (name) + return name->lastToken(); + else if (typename_token) + return typename_token + 1; + return using_token + 1; } void UsingDirectiveAST::accept0(ASTVisitor *visitor) From 7c6c439c69788f9b9e1a4b132a03f1b84e78ccbc Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:09:08 +0100 Subject: [PATCH 175/230] UsingDirectiveAST::lastToken(). --- shared/cplusplus/AST.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index e0f1582db6d..911af02e53c 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2772,8 +2772,13 @@ unsigned UsingDirectiveAST::firstToken() const unsigned UsingDirectiveAST::lastToken() const { - assert(0 && "review me"); - return semicolon_token + 1; + if (semicolon_token) + return semicolon_token + 1; + else if (name) + return name->lastToken(); + else if (namespace_token) + return namespace_token + 1; + return using_token + 1; } void WhileStatementAST::accept0(ASTVisitor *visitor) From 38be56407b64b81cf7ff0674e1192c8cef614c48 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:10:39 +0100 Subject: [PATCH 176/230] WhileStatementAST::lastToken(). --- shared/cplusplus/AST.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index 911af02e53c..ff19e4439b8 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -2796,10 +2796,15 @@ unsigned WhileStatementAST::firstToken() const unsigned WhileStatementAST::lastToken() const { - assert(0 && "review me"); if (statement) return statement->lastToken(); - return rparen_token + 1; + else if (rparen_token) + return rparen_token + 1; + else if (condition) + return condition->lastToken(); + else if (lparen_token) + return lparen_token + 1; + return while_token + 1; } CPLUSPLUS_END_NAMESPACE From 03854281da39790878062c00eb46b03c9b5beeb1 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:13:49 +0100 Subject: [PATCH 177/230] Accept the next-declarator in NewDeclaratorAST::accept() and implemented NewDeclarator::lastToken(). --- shared/cplusplus/AST.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index ff19e4439b8..cf37e5cb593 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1821,9 +1821,11 @@ void NewDeclaratorAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op; - ptr_op = static_cast(ptr_op->next)) + ptr_op = static_cast(ptr_op->next)) { accept(ptr_op, visitor); - // ### TODO accept the brackets + } + + accept(declarator, visitor); } } @@ -1834,10 +1836,14 @@ unsigned NewDeclaratorAST::firstToken() const unsigned NewDeclaratorAST::lastToken() const { - assert(0 && "review me"); if (declarator) return declarator->lastToken(); - assert(0); // ### implement me + + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { + if (! it->next) + return it->lastToken(); + } + return 0; } From af89fb1bfcf3024604322214496430d216f4843e Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:15:28 +0100 Subject: [PATCH 178/230] Implemented ExpressionListAST::accept(). --- shared/cplusplus/AST.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/AST.cpp b/shared/cplusplus/AST.cpp index cf37e5cb593..282b5876c89 100644 --- a/shared/cplusplus/AST.cpp +++ b/shared/cplusplus/AST.cpp @@ -1352,8 +1352,12 @@ unsigned ExceptionSpecificationAST::lastToken() const return throw_token + 1; } -void ExpressionListAST::accept0(ASTVisitor *) -{ assert(0); } +void ExpressionListAST::accept0(ASTVisitor *visitor) +{ + for (const ExpressionListAST *it = this; it; it = it->next) { + accept(it->expression, visitor); + } +} unsigned ExpressionListAST::firstToken() const { From e28c1255f24351a16707b7a95bf32a78a5ce72b8 Mon Sep 17 00:00:00 2001 From: con Date: Tue, 6 Jan 2009 12:16:36 +0100 Subject: [PATCH 179/230] Fixes: - Retain search term in locator when selecting different filter --- src/plugins/quickopen/quickopentoolwindow.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/plugins/quickopen/quickopentoolwindow.cpp b/src/plugins/quickopen/quickopentoolwindow.cpp index 415e347a3ac..b3232147f37 100644 --- a/src/plugins/quickopen/quickopentoolwindow.cpp +++ b/src/plugins/quickopen/quickopentoolwindow.cpp @@ -451,14 +451,25 @@ void QuickOpenToolWindow::show(const QString &text, int selectionStart, int sele void QuickOpenToolWindow::filterSelected() { - const char * const TEXT = ""; + QString searchText = ""; QAction *action = qobject_cast(sender()); QTC_ASSERT(action, return); IQuickOpenFilter *filter = action->data().value(); QTC_ASSERT(filter, return); - show(filter->shortcutString() + " " + TEXT, + QString currentText = m_fileLineEdit->text().trimmed(); + // add shortcut string at front or replace existing shortcut string + if (!currentText.isEmpty()) { + searchText = currentText; + foreach (IQuickOpenFilter *otherfilter, m_quickOpenPlugin->filter()) { + if (currentText.startsWith(otherfilter->shortcutString() + " ")) { + searchText = currentText.mid(otherfilter->shortcutString().length()+1); + break; + } + } + } + show(filter->shortcutString() + " " + searchText, filter->shortcutString().length() + 1, - QString(TEXT).length()); + searchText.length()); updateCompletionList(m_fileLineEdit->text()); m_fileLineEdit->setFocus(); } From a0b4b8cd5ca975b347d2dbd2e986834700ff9824 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 12:20:45 +0100 Subject: [PATCH 180/230] add tiny test application --- tests/manual/fakevim/fakevim.pro | 11 ++++++ tests/manual/fakevim/main.cpp | 58 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tests/manual/fakevim/fakevim.pro create mode 100644 tests/manual/fakevim/main.cpp diff --git a/tests/manual/fakevim/fakevim.pro b/tests/manual/fakevim/fakevim.pro new file mode 100644 index 00000000000..ed3046b76c9 --- /dev/null +++ b/tests/manual/fakevim/fakevim.pro @@ -0,0 +1,11 @@ + +FAKEVIMHOME = ../../../src/plugins/fakevim + +SOURCES += \ + main.cpp \ + $$FAKEVIMHOME/handler.cpp + +HEADERS += \ + $$FAKEVIMHOME/handler.h + +INCLUDEPATH += $$FAKEVIMHOME diff --git a/tests/manual/fakevim/main.cpp b/tests/manual/fakevim/main.cpp new file mode 100644 index 00000000000..ca6fb3f6518 --- /dev/null +++ b/tests/manual/fakevim/main.cpp @@ -0,0 +1,58 @@ + +#include "handler.h" + +#include + +#include +#include +#include +#include +#include + +using namespace FakeVim::Internal; + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QStringList args = app.arguments(); + (void) args.takeFirst(); + + QWidget *widget = 0; + QString title; + bool usePlainTextEdit = args.size() < 2; + if (usePlainTextEdit) { + widget = new QPlainTextEdit; + title = "PlainTextEdit"; + } else { + widget = new QTextEdit; + title = "TextEdit"; + } + widget->resize(450, 350); + widget->setFocus(); + + FakeVimHandler fakeVim; + + QMainWindow mw; + mw.setWindowTitle("Fakevim (" + title + ")"); + mw.setCentralWidget(widget); + mw.resize(500, 650); + mw.move(0, 0); + mw.show(); + + QFont font = mw.statusBar()->font(); + font.setFamily("Monospace"); + font.setStretch(QFont::SemiCondensed); + mw.statusBar()->setFont(font); + + QObject::connect(&fakeVim, SIGNAL(commandBufferChanged(QString)), + mw.statusBar(), SLOT(showMessage(QString))); + QObject::connect(&fakeVim, SIGNAL(quitRequested(QWidget *)), + &app, SLOT(quit())); + + fakeVim.addWidget(widget); + if (args.size() >= 1) + fakeVim.handleCommand(widget, "r " + args.at(0)); + + return app.exec(); +} From c70af84708d22b295a0686cfcdb8a15056b116ef Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 12:38:32 +0100 Subject: [PATCH 181/230] Added another simple refactoring operation. Comment enum definitions. --- tests/manual/cplusplus/main.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/manual/cplusplus/main.cpp b/tests/manual/cplusplus/main.cpp index e5a68d40586..b4b9b8456d8 100644 --- a/tests/manual/cplusplus/main.cpp +++ b/tests/manual/cplusplus/main.cpp @@ -119,6 +119,25 @@ public: } protected: + bool isEnumOrTypedefEnum(SpecifierAST *spec) { + if (! spec) + return false; + if (SimpleSpecifierAST *simpleSpec = spec->asSimpleSpecifier()) { + if (tokenKind(simpleSpec->specifier_token) == T_TYPEDEF) + return isEnumOrTypedefEnum(spec->next); + } + return spec->asEnumSpecifier() != 0; + } + virtual bool visit(SimpleDeclarationAST *ast) { + if (isEnumOrTypedefEnum(ast->decl_specifier_seq)) { + //remove(ast->firstToken(), ast->lastToken()); + insertTextBefore(ast->firstToken(), "/* #REF# removed "); + insertTextAfter(ast->lastToken() - 1, "*/"); + return true; + } + return true; + } + virtual bool visit(AccessDeclarationAST *ast) { if (tokenKind(ast->access_specifier_token) == T_PRIVATE) { @@ -164,7 +183,11 @@ protected: if (ast->lbrace_token) insertTextAfter(ast->lbrace_token, " Q_OBJECT\n"); - return true; + for (DeclarationAST *it = ast->member_specifiers; it; it = it->next) { + accept(it); + } + + return false; } }; From 5a32af444cb455e50d74056966bd137ca7482e0a Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 13:03:59 +0100 Subject: [PATCH 182/230] use textedit's overwrite modus for proper cursor display. this works with proportional fonts, too. --- src/plugins/fakevim/handler.cpp | 61 +++++++++++++++++++-------------- tests/manual/fakevim/main.cpp | 9 +++-- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index de1c5a6d2f6..cd19d2742a7 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -183,6 +183,10 @@ private: int readLineCode(QString &cmd); QTextCursor selectRange(int beginLine, int endLine); + void enterInsertMode(); +public: + void enterCommandMode(); + public: QTextEdit *m_textedit; QPlainTextEdit *m_plaintextedit; @@ -601,17 +605,14 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) moveToFirstNonBlankOnLine(); finishMovement(); } else if (key == 'i') { - m_mode = InsertMode; - m_lastInsertion.clear(); + enterInsertMode(); updateMiniBuffer(); } else if (key == 'I') { - m_mode = InsertMode; + enterInsertMode(); if (m_gflag) m_tc.movePosition(StartOfLine, KeepAnchor); else moveToFirstNonBlankOnLine(); - m_tc.clearSelection(); - m_lastInsertion.clear(); } else if (key == 'j' || key == Key_Down) { m_tc.movePosition(Down, KeepAnchor, count()); finishMovement(); @@ -649,13 +650,11 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else if (key == 'N') { search(lastSearchString(), !m_lastSearchForward); } else if (key == 'o') { - m_mode = InsertMode; - m_lastInsertion.clear(); + enterInsertMode(); m_tc.movePosition(EndOfLine, MoveAnchor); m_tc.insertText("\n"); } else if (key == 'O') { - m_mode = InsertMode; - m_lastInsertion.clear(); + enterInsertMode(); m_tc.movePosition(StartOfLine, MoveAnchor); m_tc.movePosition(Left, MoveAnchor, 1); m_tc.insertText("\n"); @@ -747,7 +746,7 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) } recordInsert(m_tc.position() - m_lastInsertion.size(), data); m_tc.movePosition(Left, MoveAnchor, qMin(1, leftDist())); - m_mode = CommandMode; + enterCommandMode(); } else if (key == Key_Left) { m_tc.movePosition(Left, MoveAnchor, 1); m_lastInsertion.clear(); @@ -793,11 +792,11 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) if (key == Key_Escape) { m_commandBuffer.clear(); m_commandCode = 0; - m_mode = CommandMode; + enterCommandMode(); updateMiniBuffer(); } else if (key == Key_Backspace) { if (m_commandBuffer.isEmpty()) - m_mode = CommandMode; + enterCommandMode(); else m_commandBuffer.chop(1); updateMiniBuffer(); @@ -808,7 +807,7 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) handleExCommand(m_commandBuffer); m_commandCode = 0; } - m_mode = CommandMode; + enterCommandMode(); } else if (key == Key_Return && isSearchCommand()) { if (!m_commandBuffer.isEmpty()) { m_searchHistory.takeLast(); @@ -817,7 +816,7 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) search(lastSearchString(), m_lastSearchForward); m_commandCode = 0; } - m_mode = CommandMode; + enterCommandMode(); updateMiniBuffer(); } else if (key == Key_Up && isSearchCommand()) { // FIXME: This and the three cases below are wrong as vim @@ -919,7 +918,6 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0) int line = readLineCode(cmd); if (line != -1) - m_mode = CommandMode; beginLine = line; if (cmd.startsWith(',')) { @@ -976,7 +974,7 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0) m_commandBuffer = QString("\"%1\" %2 %3L, %4C written") .arg(fileName).arg(exists ? " " : " [New] ") .arg(ba.count('\n')).arg(ba.size()); - m_mode = CommandMode; + enterCommandMode(); updateMiniBuffer(); } } else if (cmd.startsWith("r ")) { // :r @@ -988,7 +986,7 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0) EDITOR(setPlainText(data)); m_commandBuffer = QString("\"%1\" %2L, %3C") .arg(m_currentFileName).arg(data.count('\n')).arg(data.size()); - m_mode = CommandMode; + enterCommandMode(); updateMiniBuffer(); } else { showMessage("E492: Not an editor command: " + cmd0); @@ -1306,7 +1304,22 @@ void FakeVimHandler::Private::recordRemove(int position, const QString &data) m_undoStack.push(op); m_redoStack.clear(); } - + +void FakeVimHandler::Private::enterInsertMode() +{ + EDITOR(setOverwriteMode(false)); + m_mode = InsertMode; + m_lastInsertion.clear(); +} + +void FakeVimHandler::Private::enterCommandMode() +{ + if (editor()) + EDITOR(setOverwriteMode(true)); + m_mode = CommandMode; +} + + /////////////////////////////////////////////////////////////////////// // // FakeVimHandler @@ -1332,23 +1345,19 @@ bool FakeVimHandler::eventFilter(QObject *ob, QEvent *ev) void FakeVimHandler::addWidget(QWidget *widget) { widget->installEventFilter(this); - QFont font = widget->font(); - //: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1 - //font.setFamily("Misc"); - font.setFamily("Monospace"); - font.setStretch(QFont::SemiCondensed); - widget->setFont(font); + d->enterCommandMode(); if (QTextEdit *ed = qobject_cast(widget)) { - ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x'))); + //ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x'))); ed->setLineWrapMode(QTextEdit::NoWrap); } else if (QPlainTextEdit *ed = qobject_cast(widget)) { - ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x'))); + //ed->setCursorWidth(QFontMetrics(ed->font()).width(QChar('x'))); ed->setLineWrapMode(QPlainTextEdit::NoWrap); } } void FakeVimHandler::removeWidget(QWidget *widget) { + d->enterCommandMode(); widget->removeEventFilter(this); } diff --git a/tests/manual/fakevim/main.cpp b/tests/manual/fakevim/main.cpp index ca6fb3f6518..8c504a62a81 100644 --- a/tests/manual/fakevim/main.cpp +++ b/tests/manual/fakevim/main.cpp @@ -31,6 +31,7 @@ int main(int argc, char *argv[]) widget->resize(450, 350); widget->setFocus(); + FakeVimHandler fakeVim; QMainWindow mw; @@ -40,9 +41,13 @@ int main(int argc, char *argv[]) mw.move(0, 0); mw.show(); - QFont font = mw.statusBar()->font(); + QFont font = widget->font(); + //: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1 + //font.setFamily("Misc"); font.setFamily("Monospace"); - font.setStretch(QFont::SemiCondensed); + //font.setStretch(QFont::SemiCondensed); + + widget->setFont(font); mw.statusBar()->setFont(font); QObject::connect(&fakeVim, SIGNAL(commandBufferChanged(QString)), From 514b16c815c8600b18dd52fdd63e542548727609 Mon Sep 17 00:00:00 2001 From: con Date: Tue, 6 Jan 2009 13:59:17 +0100 Subject: [PATCH 183/230] Fixes: - Unhighlight search results when search filter changes Task: - 237668 --- src/plugins/find/currentdocumentfind.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/find/currentdocumentfind.cpp b/src/plugins/find/currentdocumentfind.cpp index 26ed8dd0492..ed0a61c8319 100644 --- a/src/plugins/find/currentdocumentfind.cpp +++ b/src/plugins/find/currentdocumentfind.cpp @@ -150,6 +150,8 @@ void CurrentDocumentFind::updateCurrentFindFilter(QWidget *old, QWidget *now) if (!impl) return; removeFindSupportConnections(); + if (m_currentFind) + m_currentFind->highlightAll(QString(), 0); m_currentWidget = candidate; m_currentFind = impl; if (m_currentFind) { From b0dd75b460e354f49c8c83b350d2b981f563e3e4 Mon Sep 17 00:00:00 2001 From: con Date: Tue, 6 Jan 2009 14:34:05 +0100 Subject: [PATCH 184/230] Fixes: - Fix the unhighlight fix. Details: - We shouldn't do anything if the find filter doesn't change. That probably also avoids multiple event filters on the same widget. --- src/plugins/find/currentdocumentfind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/find/currentdocumentfind.cpp b/src/plugins/find/currentdocumentfind.cpp index ed0a61c8319..dd25564a437 100644 --- a/src/plugins/find/currentdocumentfind.cpp +++ b/src/plugins/find/currentdocumentfind.cpp @@ -147,7 +147,7 @@ void CurrentDocumentFind::updateCurrentFindFilter(QWidget *old, QWidget *now) if (!impl) candidate = candidate->parentWidget(); } - if (!impl) + if (!impl || impl == m_currentFind) return; removeFindSupportConnections(); if (m_currentFind) From 26c81c54e3820b42243165ca8bd5e4426c35dd6c Mon Sep 17 00:00:00 2001 From: con Date: Tue, 6 Jan 2009 14:51:45 +0100 Subject: [PATCH 185/230] Fixes: - Multiple pro/pri entries in locator project filters Task: - 238352 Details: - Since a while now, pro and pri files are directly part of a project's file list. --- src/plugins/qt4projectmanager/qt4project.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp index 2a7fd0c242c..dd61dbde099 100644 --- a/src/plugins/qt4projectmanager/qt4project.cpp +++ b/src/plugins/qt4projectmanager/qt4project.cpp @@ -566,7 +566,6 @@ QStringList Qt4Project::files(FilesMode fileMode) const if (fileMode == AllFiles) files += m_projectFiles->generatedFiles[i]; } - files += m_projectFiles->proFiles; return files; } From e43e09ee5ff43ef69c60b8a12f66c166c6f44272 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 15:15:13 +0100 Subject: [PATCH 186/230] Test the pretty printer. --- tests/manual/cplusplus/main.cpp | 52 ++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/tests/manual/cplusplus/main.cpp b/tests/manual/cplusplus/main.cpp index b4b9b8456d8..019683f0615 100644 --- a/tests/manual/cplusplus/main.cpp +++ b/tests/manual/cplusplus/main.cpp @@ -37,13 +37,18 @@ #include #include #include +#include -#include -#include +#include +#include +#include +#include +#include #include #include #include +#include class Rewrite { @@ -191,8 +196,35 @@ protected: } }; -int main(int, char *[]) +int main(int argc, char *argv[]) { + QCoreApplication app(argc, argv); + + QStringList args = app.arguments(); + const QString appName = args.first(); + args.removeFirst(); + + bool test_rewriter = false; + bool test_pretty_printer = false; + + foreach (QString arg, args) { + if (arg == QLatin1String("--test-rewriter")) + test_rewriter = true; + else if (arg == QLatin1String("--test-pretty-printer")) + test_pretty_printer = true; + else if (arg == QLatin1String("--help")) { + const QFileInfo appInfo(appName); + const QByteArray appFileName = QFile::encodeName(appInfo.fileName()); + + printf("Usage: %s [options]\n" + " --help Display ths information\n" + " --test-rewriter Test the tree rewriter\n" + " --test-pretty-printer Test the pretty printer\n", + appFileName.constData()); + return EXIT_SUCCESS; + } + } + QFile in; if (! in.open(stdin, QFile::ReadOnly)) return EXIT_FAILURE; @@ -217,10 +249,14 @@ int main(int, char *[]) } // test the rewriter - QByteArray out; - SimpleRefactor refactor(&control); - refactor(&unit, source, &out); - printf("%s\n", out.constData()); - + if (test_rewriter) { + QByteArray out; + SimpleRefactor refactor(&control); + refactor(&unit, source, &out); + printf("%s\n", out.constData()); + } else if (test_pretty_printer) { + PrettyPrinter pp(&control, std::cout); + pp(unit.ast()); + } return EXIT_SUCCESS; } From dce0855fc67ee1d2512f4994c818600908e23848 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 6 Jan 2009 15:23:59 +0100 Subject: [PATCH 187/230] Show how to replace AST nodes. --- tests/manual/cplusplus/main.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/manual/cplusplus/main.cpp b/tests/manual/cplusplus/main.cpp index 019683f0615..b8a8e328708 100644 --- a/tests/manual/cplusplus/main.cpp +++ b/tests/manual/cplusplus/main.cpp @@ -49,6 +49,7 @@ #include #include #include +#include class Rewrite { @@ -194,6 +195,19 @@ protected: return false; } + + virtual bool visit(CppCastExpressionAST *ast) { + // Replace the C++ cast expression (e.g. static_cast(a)) with + // the one generated by the pretty printer. + std::ostringstream o; + PrettyPrinter pp(control(), o); + pp(ast); + remove(ast->firstToken(), ast->lastToken()); + const std::string str = o.str(); + insertTextBefore(ast->firstToken(), str.c_str()); + insertTextBefore(ast->firstToken(), "/* #REF# beautiful cast */ "); + return false; + } }; int main(int argc, char *argv[]) From 2f2588bee79e410736de6897d9555c42b0cc58e1 Mon Sep 17 00:00:00 2001 From: con Date: Tue, 6 Jan 2009 15:56:47 +0100 Subject: [PATCH 188/230] Fixes: - API doc main page --- doc/api/qtcreator-api.qdoc | 55 ++++++++++++++++++---------- doc/api/qtcreator-api.qdocconf | 6 ++- src/libs/aggregation/aggregate.cpp | 6 +-- src/libs/extensionsystem/iplugin.cpp | 1 + 4 files changed, 44 insertions(+), 24 deletions(-) diff --git a/doc/api/qtcreator-api.qdoc b/doc/api/qtcreator-api.qdoc index 2c939b21bb4..5ac78d98069 100644 --- a/doc/api/qtcreator-api.qdoc +++ b/doc/api/qtcreator-api.qdoc @@ -3,7 +3,28 @@ \title Qt Creator Qt Creator is Qt Software's crossplatform IDE. The core of Qt Creator is - basically only a \l{Plugin Loader Framework}{plugin loader}. + basically only a \l{ExtensionSystem}{plugin loader}. + + \section1 Core Libraries + + There are a few core libraries used by many parts of Qt Creator. + + \table + \header + \o Library Name + \o Description + + \row + \o \l{Aggregation}{Aggregation} + \o Adds functionality for "glueing" QObjects of different + types together, so you can "cast" between them. + + \row + \o \l{ExtensionSystem}{ExtensionSystem} + \o Implements the plugin loader framework. Provides a base class for plugins and + basic mechanisms for plugin interaction like an object pool. + + \endtable \section1 Plugins @@ -18,46 +39,42 @@ \o Description \row - \o \l{Core Plugin} {Core} + \o \l{Core} {Core} \o The core plugin. Provides the main window and managers for editors, actions, mode windows and files, just to mention the most important ones. \endtable - */ /*! \page classes.html - \title Qt Creator Classes and Namespaces - - \section1 Classes + \title Qt Creator Classes \generatelist classes - - \section1 Namespaces - - \generatelist{namespaces} */ /*! - \page interfaces.html - \title Interfaces + \page namespaces.html + \title Qt Creator Namespaces + + \generatelist namespaces +*/ + +/*! + \page mainclasses.html + \title Qt Creator Main Classes + \generatelist mainclasses */ /*! \page functions.html - \title Member Function Index + \title Qt Creator Functions + \generatelist functionindex */ -/*! - \group pluginloader - - \title Plugin Loader Framework -*/ - /*! \group qtc diff --git a/doc/api/qtcreator-api.qdocconf b/doc/api/qtcreator-api.qdocconf index 336aa27edcf..92c40b8a388 100644 --- a/doc/api/qtcreator-api.qdocconf +++ b/doc/api/qtcreator-api.qdocconf @@ -4,11 +4,13 @@ description = Qt Creator API Documentation language = Cpp headerdirs = . \ + ../../src/libs/aggregation \ ../../src/libs/extensionsystem \ ../../src/plugins/core \ ../../src/plugins/core/actionmanager sourcedirs = . \ + ../../src/libs/aggregation \ ../../src/libs/extensionsystem \ ../../src/plugins/core \ ../../src/plugins/core/actionmanager @@ -20,8 +22,8 @@ imagedirs = . indexes = $QTDIR/doc/html/qt.index -outputdir = ./html-api -base = file:./html-api +outputdir = ./html +base = file:./html versionsym = 0.9.2 codeindent = 1 diff --git a/src/libs/aggregation/aggregate.cpp b/src/libs/aggregation/aggregate.cpp index 6fd7414dfc2..1dd6ce03392 100644 --- a/src/libs/aggregation/aggregate.cpp +++ b/src/libs/aggregation/aggregate.cpp @@ -37,12 +37,12 @@ /*! \namespace Aggregation - \brief Contains support for bundling related components, such that - each component exposes the properties and behavior of the + \brief The Aggregation namespace contains support for bundling related components, + such that each component exposes the properties and behavior of the other components to the outside. Components that are bundled to an Aggregate can be "cast" to each other - and have a coupled life cycle. See the documentation of Aggregate for + and have a coupled life cycle. See the documentation of Aggregation::Aggregate for details and examples. */ diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp index 70d2366ea9a..0ce65bf5c0a 100644 --- a/src/libs/extensionsystem/iplugin.cpp +++ b/src/libs/extensionsystem/iplugin.cpp @@ -38,6 +38,7 @@ /*! \class ExtensionSystem::IPlugin + \mainclass \brief Base class for all plugins. The IPlugin class is an abstract class that must be implemented From 9da009aaa16cf0b60f7b8503027eea6c196ad9ec Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 16:04:34 +0100 Subject: [PATCH 189/230] uses enums to distinguish searching and ex commands --- src/plugins/fakevim/handler.cpp | 108 ++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 46 deletions(-) diff --git a/src/plugins/fakevim/handler.cpp b/src/plugins/fakevim/handler.cpp index cd19d2742a7..0427a4ee022 100644 --- a/src/plugins/fakevim/handler.cpp +++ b/src/plugins/fakevim/handler.cpp @@ -52,14 +52,15 @@ using namespace FakeVim::Internal; -#define StartOfLine QTextCursor::StartOfLine -#define EndOfLine QTextCursor::EndOfLine -#define MoveAnchor QTextCursor::MoveAnchor -#define KeepAnchor QTextCursor::KeepAnchor -#define Up QTextCursor::Up -#define Down QTextCursor::Down -#define Right QTextCursor::Right -#define Left QTextCursor::Left +#define StartOfLine QTextCursor::StartOfLine +#define EndOfLine QTextCursor::EndOfLine +#define MoveAnchor QTextCursor::MoveAnchor +#define KeepAnchor QTextCursor::KeepAnchor +#define Up QTextCursor::Up +#define Down QTextCursor::Down +#define Right QTextCursor::Right +#define Left QTextCursor::Left +#define EndOfDocument QTextCursor::End /////////////////////////////////////////////////////////////////////// @@ -78,7 +79,9 @@ enum Mode { InsertMode, CommandMode, - ExMode + ExMode, + SearchForwardMode, + SearchBackwardMode, }; enum SubMode @@ -87,7 +90,7 @@ enum SubMode RegisterSubMode, ChangeSubMode, DeleteSubMode, - ZSubMode + ZSubMode, }; enum SubSubMode @@ -147,7 +150,7 @@ private: void handleInsertMode(int key, const QString &text); void handleCommandMode(int key, const QString &text); void handleRegisterMode(int key, const QString &text); - void handleExMode(int key, const QString &text); + void handleMiniBufferModes(int key, const QString &text); void finishMovement(const QString &text = QString()); void updateMiniBuffer(); void updateSelection(); @@ -207,9 +210,8 @@ private: bool m_fakeEnd; QWidget *editor() const; - bool isSearchCommand() const - { return m_commandCode == '?' || m_commandCode == '/'; } - int m_commandCode; // ?, /, : ... + bool isSearchMode() const + { return m_mode == SearchForwardMode || m_mode == SearchBackwardMode; } int m_gflag; // whether current command started with 'g' QString m_commandBuffer; @@ -260,7 +262,6 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent) m_mode = CommandMode; m_submode = NoSubMode; m_subsubmode = NoSubSubMode; - m_commandCode = 0; m_fakeEnd = false; m_lastSearchForward = true; m_register = '"'; @@ -317,8 +318,9 @@ void FakeVimHandler::Private::handleKey(int key, const QString &text) handleInsertMode(key, text); else if (m_mode == CommandMode) handleCommandMode(key, text); - else if (m_mode == ExMode) - handleExMode(key, text); + else if (m_mode == ExMode || m_mode == SearchForwardMode + || m_mode == SearchBackwardMode) + handleMiniBufferModes(key, text); } void FakeVimHandler::Private::finishMovement(const QString &dotCommand) @@ -413,7 +415,12 @@ void FakeVimHandler::Private::updateMiniBuffer() } else if (m_mode == InsertMode) { msg = "-- INSERT --"; } else { - msg = QChar(m_commandCode ? m_commandCode : ' '); + if (m_mode == SearchForwardMode) + msg += '/'; + else if (m_mode == SearchBackwardMode) + msg += '?'; + else if (m_mode == ExMode) + msg += ':'; foreach (QChar c, m_commandBuffer) { if (c.unicode() < 32) { msg += '^'; @@ -502,17 +509,21 @@ void FakeVimHandler::Private::handleCommandMode(int key, const QString &text) } else { m_mvcount.append(QChar(key)); } - } else if (key == ':' || key == '/' || key == '?') { - m_commandCode = key; + } else if (key == ':') { m_mode = ExMode; m_commandBuffer.clear(); - if (isSearchCommand()) { - m_searchHistory.append(QString()); - m_searchHistoryIndex = m_searchHistory.size() - 1; - } else { - m_commandHistory.append(QString()); - m_commandHistoryIndex = m_commandHistory.size() - 1; + if (m_visualMode != NoVisualMode) { + m_commandBuffer = "'<,'>"; + leaveVisualMode(); } + m_commandHistory.append(QString()); + m_commandHistoryIndex = m_commandHistory.size() - 1; + updateMiniBuffer(); + } else if (key == '/' || key == '?') { + m_mode = (key == '/') ? SearchForwardMode : SearchBackwardMode; + m_commandBuffer.clear(); + m_searchHistory.append(QString()); + m_searchHistoryIndex = m_searchHistory.size() - 1; updateMiniBuffer(); } else if (key == '`') { m_subsubmode = BackTickSubSubMode; @@ -785,13 +796,12 @@ void FakeVimHandler::Private::handleInsertMode(int key, const QString &text) updateMiniBuffer(); } -void FakeVimHandler::Private::handleExMode(int key, const QString &text) +void FakeVimHandler::Private::handleMiniBufferModes(int key, const QString &text) { Q_UNUSED(text) if (key == Key_Escape) { m_commandBuffer.clear(); - m_commandCode = 0; enterCommandMode(); updateMiniBuffer(); } else if (key == Key_Backspace) { @@ -800,25 +810,23 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) else m_commandBuffer.chop(1); updateMiniBuffer(); - } else if (key == Key_Return && m_commandCode == ':') { + } else if (key == Key_Return && m_mode == ExMode) { if (!m_commandBuffer.isEmpty()) { m_commandHistory.takeLast(); m_commandHistory.append(m_commandBuffer); handleExCommand(m_commandBuffer); - m_commandCode = 0; } enterCommandMode(); - } else if (key == Key_Return && isSearchCommand()) { + } else if (key == Key_Return && isSearchMode()) { if (!m_commandBuffer.isEmpty()) { m_searchHistory.takeLast(); m_searchHistory.append(m_commandBuffer); - m_lastSearchForward = (m_commandCode == '/'); + m_lastSearchForward = (m_mode == SearchForwardMode); search(lastSearchString(), m_lastSearchForward); - m_commandCode = 0; } enterCommandMode(); updateMiniBuffer(); - } else if (key == Key_Up && isSearchCommand()) { + } else if (key == Key_Up && isSearchMode()) { // FIXME: This and the three cases below are wrong as vim // takes only matching entires in the history into account. if (m_searchHistoryIndex > 0) { @@ -826,19 +834,19 @@ void FakeVimHandler::Private::handleExMode(int key, const QString &text) m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); updateMiniBuffer(); } - } else if (key == Key_Up && m_commandCode == ':') { + } else if (key == Key_Up && m_mode == ExMode) { if (m_commandHistoryIndex > 0) { --m_commandHistoryIndex; m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex); updateMiniBuffer(); } - } else if (key == Key_Down && isSearchCommand()) { + } else if (key == Key_Down && isSearchMode()) { if (m_searchHistoryIndex < m_searchHistory.size() - 1) { ++m_searchHistoryIndex; m_commandBuffer = m_searchHistory.at(m_searchHistoryIndex); updateMiniBuffer(); } - } else if (key == Key_Down && m_commandCode == ':') { + } else if (key == Key_Down && m_mode == ExMode) { if (m_commandHistoryIndex < m_commandHistory.size() - 1) { ++m_commandHistoryIndex; m_commandBuffer = m_commandHistory.at(m_commandHistoryIndex); @@ -875,6 +883,7 @@ int FakeVimHandler::Private::readLineCode(QString &cmd) } if (c == '\'' && !cmd.isEmpty()) { int pos = m_marks.value(cmd.at(0).unicode()); + qDebug() << " MARK: " << cmd.at(0) << pos << lineForPosition(pos); if (!pos) { showMessage(tr("E20: Mark '%1' not set").arg(cmd.at(0))); return -1; @@ -903,7 +912,12 @@ QTextCursor FakeVimHandler::Private::selectRange(int beginLine, int endLine) { QTextCursor tc = m_tc; tc.setPosition(positionForLine(beginLine), MoveAnchor); - tc.setPosition(positionForLine(endLine + 1), KeepAnchor); + if (endLine == linesInDocument()) { + tc.setPosition(positionForLine(endLine), KeepAnchor); + tc.movePosition(EndOfLine, KeepAnchor); + } else { + tc.setPosition(positionForLine(endLine + 1), KeepAnchor); + } return tc; } @@ -949,11 +963,13 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0) m_registers[reg.at(0).unicode()] = tc.selection().toPlainText(); tc.removeSelectedText(); } else if (reWrite.indexIn(cmd) != -1) { // :w + enterCommandMode(); bool noArgs = (beginLine == -1); if (beginLine == -1) beginLine = 0; if (endLine == -1) endLine = linesInDocument(); + qDebug() << "LINES: " << beginLine << endLine; bool forced = cmd.startsWith("w!"); QString fileName = reWrite.cap(2); if (fileName.isEmpty()) @@ -961,21 +977,21 @@ void FakeVimHandler::Private::handleExCommand(const QString &cmd0) QFile file(fileName); bool exists = file.exists(); if (exists && !forced && !noArgs) { - showMessage("E13: File exists (add ! to override)"); - } else { - file.open(QIODevice::ReadWrite); + showMessage(tr("File '%1' exists (add ! to override)").arg(fileName)); + } else if (file.open(QIODevice::ReadWrite)) { QTextCursor tc = selectRange(beginLine, endLine); - QString text = tc.selection().toPlainText(); - QTextStream ts(&file); - ts << text; + qDebug() << "ANCHOR: " << tc.position() << tc.anchor() + << tc.selection().toPlainText(); + { QTextStream ts(&file); ts << tc.selection().toPlainText(); } file.close(); - file.open(QIODevice::ReadWrite); + file.open(QIODevice::ReadOnly); QByteArray ba = file.readAll(); m_commandBuffer = QString("\"%1\" %2 %3L, %4C written") .arg(fileName).arg(exists ? " " : " [New] ") .arg(ba.count('\n')).arg(ba.size()); - enterCommandMode(); updateMiniBuffer(); + } else { + showMessage(tr("Cannot open file '%1' for reading").arg(fileName)); } } else if (cmd.startsWith("r ")) { // :r m_currentFileName = cmd.mid(2); From aa3b488e79ac0050134f2d854044074e601882b1 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 6 Jan 2009 16:08:14 +0100 Subject: [PATCH 190/230] remove unused installer code to avoid confusion --- installer/TODO.txt | 12 - installer/installer.cpp | 433 ------- installer/installer.pro | 29 - installer/installer.qrc | 7 - installer/qinstaller.cpp | 1872 ----------------------------- installer/qinstaller.h | 357 ------ installer/qinstallergui.cpp | 742 ------------ installer/qinstallergui.h | 256 ---- installer/resources/license.txt | 84 -- installer/resources/logo.png | Bin 1592 -> 0 bytes installer/resources/watermark.png | Bin 14462 -> 0 bytes 11 files changed, 3792 deletions(-) delete mode 100644 installer/TODO.txt delete mode 100644 installer/installer.cpp delete mode 100644 installer/installer.pro delete mode 100644 installer/installer.qrc delete mode 100644 installer/qinstaller.cpp delete mode 100644 installer/qinstaller.h delete mode 100644 installer/qinstallergui.cpp delete mode 100644 installer/qinstallergui.h delete mode 100644 installer/resources/license.txt delete mode 100644 installer/resources/logo.png delete mode 100644 installer/resources/watermark.png diff --git a/installer/TODO.txt b/installer/TODO.txt deleted file mode 100644 index 57aed144307..00000000000 --- a/installer/TODO.txt +++ /dev/null @@ -1,12 +0,0 @@ - -- installdir whitespace check done. -- installdir exist/non-empty check - - -- run '/bin/xdg-desktop-install.sh' if '/usr/bin/xdg-mime exists' -- desktop shortcut - - -- create dir '${env(APPDATA)}/Trolltech' -- start menue shortcuts - diff --git a/installer/installer.cpp b/installer/installer.cpp deleted file mode 100644 index 013d26d2b88..00000000000 --- a/installer/installer.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/*************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** -** Non-Open Source Usage -** -** Licensees may use this file in accordance with the Qt Beta Version -** License Agreement, Agreement version 2.2 provided with the Software or, -** alternatively, in accordance with the terms contained in a written -** agreement between you and Nokia. -** -** GNU General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the packaging -** of this file. Please review the following information to ensure GNU -** General Public Licensing requirements will be met: -** -** http://www.fsf.org/licensing/licenses/info/GPLv2.html and -** http://www.gnu.org/copyleft/gpl.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt GPL Exception -** version 1.3, included in the file GPL_EXCEPTION.txt in this package. -** -***************************************************************************/ - -// This file contains the QtCreator-specific part of the installer. -// It lists the files and features the installer should handle. - -#include "qinstaller.h" -#include "qinstallergui.h" - -#include -#include -#include - -#include -#include -#include -#include -#include - - -// QInstallerGui is base of the Gui part of an installer, i.e. -// the "main installer wizard". In the simplest case it's just -// a sequence of "standard" wizard pages. A few commonly used -// ones are provided already in qinstallergui.h. - - -// A custom target directory selection based due to the no-space -// restriction... - -class TargetDirectoryPage : public QInstallerTargetDirectoryPage -{ -public: - TargetDirectoryPage(QInstaller *installer) - : QInstallerTargetDirectoryPage(installer) - { - m_noSpaceLabel = new QLabel(this); - m_noSpaceLabel->setText("The directory name should not contain any space."); - m_noSpaceLabel->hide(); - insertWidget(m_noSpaceLabel, "MessageLabel"); - } - - bool isComplete() const - { - bool invalid = targetDir().contains(' '); - QPalette palette; - // We show the warning only if the user types a space. - // No need to scare him if the path is ok for us... - if (invalid) { - m_noSpaceLabel->show(); - palette.setColor(QPalette::WindowText, Qt::red); - } - m_noSpaceLabel->setPalette(palette); - return !invalid; - } - - int nextId() const - { - QFileInfo fi(targetDir()); - - if (isVisible() && fi.isDir()) { - QFileInfo fi2(targetDir() + '/' + installer()->uninstallerName()); - if (fi2.exists()) { - QMessageBox::StandardButton bt = QMessageBox::warning(wizard(), - tr("Warning"), - tr("The directory you selected exists already and contains an installaion.\n" - "Do you want to overwrite it?"), - QMessageBox::Yes | QMessageBox::No); - if (bt == QMessageBox::No) - return wizard()->currentId(); - } else { - QMessageBox::StandardButton bt = QMessageBox::warning(wizard(), - tr("Warning"), - tr("The directory you selected exists already.\n" - "Do you want to remove it and continue?"), - QMessageBox::Yes | QMessageBox::No); - if (bt == QMessageBox::No) - return wizard()->currentId(); - } - } - return QInstallerPage::nextId(); - } - -private: - QLabel *m_noSpaceLabel; -}; - - -//////////////////////////////////////////////////////////////////// -// -// QtCreatorInstallerGui -// -//////////////////////////////////////////////////////////////////// - -// QtCreatorInstallerGui is the QtCreator specific incarnation -// of a QInstallerGui. - -class QtCreatorInstallerGui : public QInstallerGui -{ -public: - QtCreatorInstallerGui(QInstaller *installer) - { - // The Gui has access to the installer backend at construction - // time. For later access it needs to store the QInstaller * - // pointer provided. Not needed in this case here. - - setWindowTitle(tr("%1 Setup").arg(installer->value("ProductName"))); - installer->connectGui(this); - - // We are happy with the default set of pages. - addPage(new QInstallerIntroductionPage(installer)); - addPage(new QInstallerLicenseAgreementPage(installer)); - //addPage(new QInstallerTargetDirectoryPage(installer)); - addPage(new TargetDirectoryPage(installer)); - if (installer->componentCount() > 1) - addPage(new QInstallerComponentSelectionPage(installer)); - addPage(new QInstallerReadyForInstallationPage(installer)); - addPage(new QInstallerPerformInstallationPage(installer)); - addPage(new QInstallerFinishedPage(installer)); - - setStartId(installer->value("GuiStartPage").toInt()); - } -}; - - -// QInstaller is base of the "backend" part of an installer, i.e. -// the part handling the installer tasks and keeping track of -// related data like the directory to install to, the name of -// the Product, version of the Product etc. - -// QtCreatorInstaller is the QtCreator specific incarnation -// of a QInstaller. It needs to list all tasks that a performed -// during installation. The tasks themselves specify what to -// do at uninstall time. - -class QtCreatorInstaller : public QInstaller -{ -public: - QtCreatorInstaller() - { - // basic product information - setValue("ProductName", "Qt Creator"); - setValue("ProductVersion", "alpha"); - - // registration information - setValue("Comments", ""); - setValue("Contact", ""); - setValue("DisplayVersion", ""); - setValue("HelpLink", ""); - setValue("Publisher", ""); - setValue("UrlAboutInfo", ""); - - // information needed at installer generation time - setValue("OutputFile", "qtcreator-installer"); - setValue("RunProgram", "@TargetDir@/bin/qtcreator"); - - // default component selection, overridable from command line - setValue("UseQtCreator", "true"); -#ifdef Q_OS_WIN - //setValue("UseQt", "true"); - //setValue("UseMinGW", "true"); -#endif - } - -private: - // tasks related to QtCreator itself. Binary, libraries etc. - void appendQtCreatorComponent() - { - QString sourceDir = value("SourceDir"); - if (sourceDir.isEmpty() && QFileInfo("../bin/qtcreator").isReadable()) - sourceDir = QLatin1String(".."); - if (sourceDir.isEmpty()) - throw QInstallerError("Missing 'SourceDir=' on command line."); - QInstallerComponent *component = new QInstallerComponent(this); - component->setValue("Name", "QtCreator"); - component->setValue("DisplayName", "Qt Creator"); - component->setValue("Description", "The Qt Creator IDE"); - component->setValue("SuggestedState", "AlwaysInstalled"); -#ifdef Q_OS_MAC - component->appendDirectoryTasks(sourceDir + "/bin/QtCreator.app", "@TargetDir@"); -#else - component->appendDirectoryTasks(sourceDir + "/bin", "@TargetDir@/bin"); - component->appendDirectoryTasks(sourceDir + "/lib", "@TargetDir@/lib"); -#endif - - QInstallerPatchFileTask *task = new QInstallerPatchFileTask(this); - task->setTargetPath("@TargetDir@/lib/Trolltech/" + libraryName("ProjectExplorer", "1.0.0")); - task->setNeedle("Clear Session"); - task->setReplacement("CLEAR SESSION"); - component->appendTask(task); - - appendComponent(component); - } - - void appendMinGWComponent() - { - QString mingwSourceDir = value("MinGWSourceDir"); - if (mingwSourceDir.isEmpty()) - throw QInstallerError("Missing 'MinGWSourceDir=' on command line."); - QInstallerComponent *component = new QInstallerComponent(this); - component->setValue("Name", "MinGW"); - component->setValue("DisplayName", "MinGW"); - component->setValue("Description", - "The MinGW environment including the g++ compiler " - "and the gdb debugger."); - component->setValue("SuggestedState", "Installed"); - component->appendDirectoryTasks(mingwSourceDir, "@TargetDir@"); - appendComponent(component); - } - - void appendQtComponent() - { - QString qtSourceDir = value("QtSourceDir"); - if (qtSourceDir.isEmpty()) - throw QInstallerError("Missing 'QtSourceDir=' on command line."); - - QInstallerComponent *component = new QInstallerComponent(this); - component->setValue("Name", "Qt Development Libraries"); - component->setValue("DisplayName", "Qt"); - component->setValue("Description", - "The Qt library files for development including " - "documentation"); - component->setValue("SuggestedState", "Installed"); - component->appendDirectoryTasks(qtSourceDir, "@TargetDir@"); - -#ifdef Q_OS_WIN - static const struct - { - const char *fileName; - const char *sourceLocation; - } libs[] = { - {"/bin/Qt3Support", "/src/qt3support/"}, - {"/bin/QtCore", "/src/corelib/"}, - {"/bin/QtGui", "/src/gui/"}, - {"/bin/QtHelp", "/tools/assistant/lib/"}, - {"/bin/QtNetwork", "/src/network/"}, - {"/bin/QtOpenGL", "/src/opengl/"}, - {"/bin/QtScript", "/src/script/"}, - {"/bin/QtSql", "/src/sql/"}, - {"/bin/QtSvg", "/src/svg/"}, - {"/bin/QtTest", "/src/testlib/"}, - {"/bin/QtWebKit", "/src/3rdparty/webkit/WebCore/"}, - {"/bin/QtXml", "/src/xml/"}, - {"/bin/QtXmlPatterns", "/src/xmlpatterns/"}, - {"/plugins/accessible/qtaccessiblecompatwidgets", - "/src/plugins/accessible/compat/"}, - {"/plugins/accessible/qtaccessiblewidgets", - "/src/plugins/accessible/widgets/"}, - {"/plugins/codecs/qcncodecs", "/src/plugins/codecs/cn/"}, - {"/plugins/codecs/qjpcodecs", "/src/plugins/codecs/jp/"}, - {"/plugins/codecs/qkrcodecs", "/src/plugins/codecs/kr/"}, - {"/plugins/codecs/qtwcodecs", "/src/plugins/codecs/tw/"}, - {"/plugins/iconengines/qsvgicon", "/src/plugins/iconengines/svgiconengine/"}, - {"/plugins/imageformats/qgif", "/src/plugins/imageformats/gif/"}, - {"/plugins/imageformats/qjpeg", "/src/plugins/imageformats/jpeg/"}, - {"/plugins/imageformats/qmng", "/src/plugins/imageformats/mng/"}, - {"/plugins/imageformats/qsvg", "/src/plugins/imageformats/svg/"}, - {"/plugins/imageformats/qtiff", "/src/plugins/imageformats/tiff/"}, - {"/plugins/sqldrivers/qsqlite", "/src/plugins/sqldrivers/sqlite/"}, - // {"/plugins/sqldrivers/qsqlodbc", "/src/plugins/sqldrivers/odbc/"} - }; - - QString debug = QLatin1String("d4.dll"); - - for (int i = 0; i != sizeof(libs) / sizeof(libs[0]); ++i) { - QInstallerPatchFileTask *task = new QInstallerPatchFileTask(this); - task->setTargetPath(QString("@TargetDir@/") + libs[i].fileName + debug); - task->setNeedle("f:/depot/qt"); - task->setReplacement(QByteArray("@TargetDir@/") + libs[i].sourceLocation); - component->appendTask(task); - } -#endif - - appendComponent(component); - } - - void createTasks() - { - // set UseXXX=false on command line to prevent inclusion of the - // respective component - if (value("UseQtCreator") == "true") - appendQtCreatorComponent(); - if (value("UseMinGW") == "true") - appendMinGWComponent(); - if (value("UseQt") == "true") - appendQtComponent(); - } -}; - - -//////////////////////////////////////////////////////////////////// -// -// QtCreatorUninstallerGui -// -//////////////////////////////////////////////////////////////////// - -class QtCreatorUninstallerGui : public QObject -{ -public: - QtCreatorUninstallerGui(QInstaller *installer) - : m_installer(installer) - {} - - int exec() - { - QMessageBox::StandardButton bt = QMessageBox::question(0, - tr("Question"), - tr("Do you want to deinstall %1 and all of its modules?") - .arg(m_installer->value("ProductName")), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No); - if (bt == QMessageBox::No) - return 0; - QWizard wizard; - wizard.addPage(new QInstallerPerformUninstallationPage(m_installer)); - wizard.show(); - return qApp->exec(); - } - -private: - QInstaller *m_installer; -}; - - - -//////////////////////////////////////////////////////////////////// -// -// The Main Driver Program -// -//////////////////////////////////////////////////////////////////// - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - QStringList args = app.arguments(); - qDebug() << "ARGS: " << args; - - QtCreatorInstaller installer; - - bool helpRequested = false; - bool guiRequested = true; - - for (int i = 1; i < args.size(); ++i) { - if (args.at(i).contains('=')) { - const QString arg = args.at(i); - const QString name = arg.section('=', 0, 0); - const QString value = arg.section('=', 1, 1); - installer.setValue(name, value); - } else if (args.at(i) == "--help" || args.at(i) == "-h") { - helpRequested = true; - } else if (args.at(i) == "--no-gui" || args.at(i) == "NoGui") { - qDebug() << "NOGUI"; - guiRequested = false; - } else if (args.at(i) == "--verbose" || args.at(i) == "Verbose") { - installer.setVerbose(true); - } else { - helpRequested = true; - } - } - - if (installer.isVerbose()) - installer.dump(); - - if (helpRequested) { - QString productName = installer.value("ProductName"); - QString str; - if (installer.isCreator()) - str = QString(" [SourceDir=]\n" - "\n Creates the %1 installer.\n").arg(productName); - else if (installer.isInstaller()) - str = QString(" [--no-gui] [=...]\n" - "\n Runs the %1 installer\n" - "\n If the '--no-gui' parameter is given, it runs " - " installer without GUI\n").arg(productName); - else if (installer.isUninstaller()) - str = QString(" [=...]\n" - "\n Runs the %1 uninstaller.\n").arg(productName); - str = "\nUsage: " + installer.installerBinaryPath() + str; - qDebug() << qPrintable(str); - return 0; - } - - if (installer.isInstaller() && guiRequested) { - QtCreatorInstallerGui gui(&installer); - gui.show(); - return app.exec(); - } - -#ifdef Q_OS_WIN - if (installer.isUninstaller()) { - QStringList newArgs = args; - newArgs.removeFirst(); - installer.restartTempUninstaller(newArgs); - return 0; - } -#endif - if ((installer.isUninstaller() || installer.isTempUninstaller()) - && guiRequested) { - QtCreatorUninstallerGui gui(&installer); - //gui.show(); - return gui.exec(); - } - - return installer.run() ? 0 : 1; -} diff --git a/installer/installer.pro b/installer/installer.pro deleted file mode 100644 index d9e59651ded..00000000000 --- a/installer/installer.pro +++ /dev/null @@ -1,29 +0,0 @@ -TEMPLATE = app -TARGET = installercreator -DEPENDPATH += . -INCLUDEPATH += . - -CONFIG -= debug -CONFIG += release - -HEADERS += \ - qinstaller.h \ - qinstallergui.h \ - -SOURCES += \ - qinstaller.cpp \ - qinstallergui.cpp \ - installer.cpp \ - -RESOURCES += \ - installer.qrc \ - -true { - OBJECTS_DIR = .tmp/ - MOC_DIR = .tmp/ - RCC_DIR = .tmp/ - UI_DIR = .tmp/ -} - -win32:LIBS += ole32.lib - diff --git a/installer/installer.qrc b/installer/installer.qrc deleted file mode 100644 index 5080febcd64..00000000000 --- a/installer/installer.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - resources/logo.png - resources/watermark.png - resources/license.txt - - diff --git a/installer/qinstaller.cpp b/installer/qinstaller.cpp deleted file mode 100644 index be72b66b2f4..00000000000 --- a/installer/qinstaller.cpp +++ /dev/null @@ -1,1872 +0,0 @@ -/*************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** -** Non-Open Source Usage -** -** Licensees may use this file in accordance with the Qt Beta Version -** License Agreement, Agreement version 2.2 provided with the Software or, -** alternatively, in accordance with the terms contained in a written -** agreement between you and Nokia. -** -** GNU General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the packaging -** of this file. Please review the following information to ensure GNU -** General Public Licensing requirements will be met: -** -** http://www.fsf.org/licensing/licenses/info/GPLv2.html and -** http://www.gnu.org/copyleft/gpl.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt GPL Exception -** version 1.3, included in the file GPL_EXCEPTION.txt in this package. -** -***************************************************************************/ - -#include "qinstaller.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef Q_OS_WIN -#include "qt_windows.h" -#include -#endif - -QT_BEGIN_NAMESPACE - -/* - FIXME: Documentation - -NAME = "Name"; -DISPLAY_NAME = "DisplayName"; -DESCRIPTION = "Description"; -TASK_COUNT = "TaskCount"; -SIZE = "ComponentSize"; -OUTPUT_FILE = "OutputFile"; -WANTED_STATE = "WantedState"; -SUGGESTED_STATE = "SuggestedState"; -PRODUCT_NAME = "ProductName"; -GUI_START_PAGE = "GuiStartPage"; -RUN_PROGRAM = "RunProgram"; -COMMENTS = "Comments"; -CONTACT = "Contact"; -DISPLAY_VERSION = "DisplayVersion"; -ESTIMATED_SIZE = "EstimatedSize"; -HELP_LINK = "HelpLink"; -INSTALL_DATE = "InstallDate"; -INSTALL_LOCATION = "InstallLocation"; -NO_MODIFY = "NoModify"; -NO_REPAIR = "NoRepair"; -PUBLISHER = "Publisher"; -UNINSTALL_STRING = "UninstallString"; -URL_INFO_ABOUT = "UrlInfoAbout"; -LOGO_PIXMAP -WATERMARK_PIXMAP -*/ - - -//static qint64 magicInstallerMarker = (0xdea0d345UL << 32) + 0x12023233UL; -//static qint64 magicUninstallerMarker = (0xdea0d345UL << 32) + 0x12023234UL; -static const qint64 magicInstallerMarker = 0x12023233UL; -static const qint64 magicUninstallerMarker = 0x12023234UL; -static const qint64 magicTempUninstallerMarker = 0x12023235UL; - -// Installer Layout: -// -// 0000: -// ... -// $comptask[0]: -// $comptask[0][0]: -// ... -// $comptask[0][$ctc0-1]: -// ... -// $comptask[$ncomp-1]: -// $comptask[$ncomp-1][0]: -// ... -// $comtaskp[$ncomp-1][$ctc-1]: -// $compvars[0]: -// ... -// $compvars[$ncomp-1]: -// $comptaskoffsets: -// -// ... -// $compvarsoffsets: -// -// ... -// $installervars: -// ... -// end - 7: -// end - 6: -// end - 5: -// end - 4: -// end - 3: -// end - 2: -// end - 1: -// -// The stuff after the binary is not present in the "Creator" incarnation - -//////////////////////////////////////////////////////////////////// -// -// Misc helpers -// -//////////////////////////////////////////////////////////////////// - -namespace { - -#define ifVerbose(s) if (!installer()->isVerbose()) {} else { qDebug() << s; } - - -QDebug &operator<<(QDebug &os, QInstallerTask *task) -{ - task->dump(os); - return os; -} - -class Dictionary : public QHash -{ -public: - typedef QHash BaseType; - - void setValue(const QString &key, const QString &val) - { - insert(key, val); - } - - void removeTemporaryKeys() - { - foreach (const QString &key, keys()) - if (key.startsWith('@')) - remove(key); - } -}; - -////////////////////////////////////////////////////////////////////// - -class Error : public QInstallerError -{ -public: - Error(const QString &m) - : QInstallerError(m) {} - // convenience - Error(const char *m, int n) - : QInstallerError(QString(QLatin1String(m)).arg(n)) {} - Error(const char *m, const QString & n) - : QInstallerError(QString(QLatin1String(m)).arg(n)) {} -private: -private: - QString m_message; -}; - -} // anonymous namespace - -static void openForWrite(QFile &file) -{ - if (!file.open(QIODevice::WriteOnly)) - throw Error("Cannot open file %1 for writing", file.fileName()); -} - -static void openForRead(QFile &file) -{ - if (!file.open(QIODevice::ReadOnly)) - throw Error("Cannot open file %1 for reading", file.fileName()); -} - -static void rawWrite(QIODevice *out, const char *buffer, qint64 size) -{ - while (size > 0) { - qint64 n = out->write(buffer, size); - if (n == -1) - throw Error("RAW WRITE FAILED: %1", size); - size -= n; - } -} - -static void rawRead(QIODevice *in, char *buffer, qint64 size) -{ - while (size > 0) { - qint64 n = in->read(buffer, size); - size -= n; - buffer += n; - if (size != 0) - qDebug() << "COULD ONLY READ " << n << "OF" << size + n << "BYTES"; - } -} - -static inline QByteArray &theBuffer(int size) -{ - static QByteArray b; - if (size > b.size()) - b.reserve(size * 3 / 2); - return b; -} - - -#if 0 -// Faster or not? -static void appendFileData(QIODevice *out, const QString &fileName) -{ - QFile file(fileName); - openForRead(file); - qint64 size = file.size(); - QInstaller::appendInt(out, size); - if (size == 0) - return; - uchar *data = file.map(0, size); - if (!data) - throw Error(QInstaller::tr("Cannot map file %1").arg(file.fileName())); - rawWrite(out, (const char *)data, size); - if (!file.unmap(data)) - throw Error(QInstaller::tr("Cannot unmap file %1").arg(file.fileName())); -} -#endif - -static void appendFileData(QIODevice *out, QIODevice *in) -{ - QTC_ASSERT(!in->isSequential(), return); - qint64 size = in->size(); - QByteArray &b = theBuffer(size); - rawRead(in, b.data(), size); - QInstaller::appendInt(out, size); - rawWrite(out, b.constData(), size); -} - -static void retrieveFileData(QIODevice *out, QIODevice *in) -{ - qint64 size = QInstaller::retrieveInt(in); - QByteArray &b = theBuffer(size); - rawRead(in, b.data(), size); - rawWrite(out, b.constData(), size); -} - -static void appendData(QIODevice *out, QIODevice *in, qint64 size) -{ - QByteArray &b = theBuffer(size); - rawRead(in, b.data(), size); - rawWrite(out, b.constData(), size); -} - -static void appendInt(QIODevice *out, qint64 n) -{ - rawWrite(out, (char*)&n, sizeof(n)); -} - -static void appendString(QIODevice *out, const QString &str) -{ - int n = str.size(); - appendInt(out, n); - rawWrite(out, (char*)str.utf16(), n * sizeof(QChar)); -} - -static void appendByteArray(QIODevice *out, const QByteArray &ba) -{ - appendInt(out, ba.size()); - rawWrite(out, ba.constData(), ba.size()); -} - -static void appendDictionary(QIODevice *out, const Dictionary &dict) -{ - appendInt(out, dict.size()); - foreach (const QString &key, dict.keys()) { - appendString(out, key); - appendString(out, dict.value(key)); - } -} - -static qint64 retrieveInt(QIODevice *in) -{ - qint64 n = 0; - in->read((char*)&n, sizeof(n)); - return n; -} - -static QString retrieveString(QIODevice *in) -{ - static QByteArray b; - qint64 n = retrieveInt(in); - if (n * int(sizeof(QChar)) > b.size()) - b.reserve(n * sizeof(QChar) * 3 / 2); - in->read(b.data(), n * sizeof(QChar)); - QString str((QChar *)b.data(), n); - return str; -} - -static QByteArray retrieveByteArray(QIODevice *in) -{ - QByteArray ba; - qint64 n = retrieveInt(in); - ba.resize(n); - rawRead(in, ba.data(), n); - return ba; -} - -static Dictionary retrieveDictionary(QIODevice *in) -{ - Dictionary dict; - for (qint64 i = retrieveInt(in); --i >= 0; ) { - QString key = retrieveString(in); - dict.insert(key, retrieveString(in)); - } - return dict; -} - -//////////////////////////////////////////////////////////////////// -// -// QInstallerComponent::Private -// -//////////////////////////////////////////////////////////////////// - -class QInstallerComponent::Private -{ -public: - QInstaller *m_installer; - Dictionary m_vars; - QList m_tasks; - - // filled before intaller runs - qint64 m_offsetInInstaller; -}; - -#if 0 - -// this is dead slow as QDirIterator::Private::advance needlessly -// creates tons of QFileInfo objects - -static void listDir - (const QString &sourcePath0, const QString &targetPath0, - QList *copyTasks, - QList *linkTasks, - int sourcePathLength) -{ - Q_UNUSED(sourcePathLength); - QDirIterator it(sourcePath0, QDir::Files, QDirIterator::Subdirectories); - const int pos = sourcePath0.size(); - while (it.hasNext()) { - QString sourcePath = it.next(); - QFileInfo sourceInfo = it.fileInfo(); - if (sourceInfo.isSymLink()) { - QFileInfo absSourceInfo(sourceInfo.absoluteFilePath()); - //QString linkTarget = sourceInfo.symLinkTarget(); - QString absLinkTarget = absSourceInfo.symLinkTarget(); - //QString relPath = sourceInfo.dir().relativeFilePath(linkTarget); - QString absRelPath = absSourceInfo.dir().relativeFilePath(absLinkTarget); - if (0) { - ifVerbose("\n\nCREATING LINK: " - << "\nSOURCE : " << sourceInfo.filePath() - << "\nSOURCE ABS: " << absSourceInfo.filePath() - //<< "\nLINK : " << linkTarget - << "\nLINK ABS: " << absLinkTarget - //<< "\nREL : " << relPath - << "\nREL ABS: " << absRelPath); - } - QString targetPath = targetPath0; - targetPath += sourcePath.midRef(pos); - //qDebug() << "LINK " << absRelPath << targetPath << targetPath0; - QInstallerLinkFileTask *task = new QInstallerLinkFileTask(m_installer); - task->setLinkTargetPath(absRelPath); - task->setTargetPath(targetPath); - task->setPermissions(sourceInfo.permissions()); - linkTasks->append(task); - } else { - QInstallerCopyFileTask *task = new QInstallerCopyFileTask(m_installer); - QString targetPath = targetPath0; - targetPath += sourcePath.midRef(pos); - //qDebug() << "COPY " << sourcePath << targetPath << targetPath0; - task->setSourcePath(sourcePath); - task->setTargetPath(targetPath); - task->setPermissions(sourceInfo.permissions()); - copyTasks.append(task); - } - } -} -#else - -static void listDir - (const QString &sourcePath, const QString &targetPath0, - QList *copyTasks, - QList *linkTasks, - QInstaller *installer, - int sourcePathLength = -1) - -{ - if (sourcePathLength == -1) - sourcePathLength = sourcePath.size(); - QFileInfo sourceInfo(sourcePath); - if (sourceInfo.isDir()) { - QDir dir(sourcePath); - dir.setSorting(QDir::Unsorted); - foreach (const QFileInfo &fi, dir.entryInfoList()) { - QString sourceFile = fi.fileName(); - if (sourceFile == QLatin1String(".") - || sourceFile == QLatin1String("..")) - continue; - listDir(sourcePath + '/' + sourceFile, targetPath0, - copyTasks, linkTasks, installer, sourcePathLength); - } - } else if (sourceInfo.isSymLink()) { - QFileInfo absSourceInfo(sourceInfo.absoluteFilePath()); - QString absLinkTarget = absSourceInfo.symLinkTarget(); - QString absRelPath = absSourceInfo.dir().relativeFilePath(absLinkTarget); - QString targetPath = targetPath0; - targetPath += sourcePath.midRef(sourcePathLength); - //qDebug() << "LINK " << absRelPath << targetPath << targetPath0; - QInstallerLinkFileTask *task = new QInstallerLinkFileTask(installer); - task->setLinkTargetPath(absRelPath); - task->setTargetPath(targetPath); - task->setPermissions(sourceInfo.permissions()); - linkTasks->append(task); - } else { - QInstallerCopyFileTask *task = new QInstallerCopyFileTask(installer); - QString targetPath = targetPath0; - targetPath += sourcePath.midRef(sourcePathLength); - //qDebug() << "COPY " << sourcePath << targetPath << targetPath0; - task->setSourcePath(sourcePath); - task->setTargetPath(targetPath); - task->setPermissions(sourceInfo.permissions()); - copyTasks->append(task); - } -} -#endif - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerComponent -// -//////////////////////////////////////////////////////////////////// - -QInstallerComponent::QInstallerComponent(QInstaller *installer) - : d(new QInstallerComponent::Private) -{ - d->m_installer = installer; -} - - -QInstallerComponent::~QInstallerComponent() -{ - qDeleteAll(d->m_tasks); - d->m_tasks.clear(); - delete d; -} - -QString QInstallerComponent::value(const QString &key, - const QString &defaultValue) const -{ - return d->m_vars.value(key, defaultValue); -} - -void QInstallerComponent::setValue(const QString &key, const QString &value) -{ - d->m_vars[key] = value; -} - -void QInstallerComponent::appendDirectoryTasks - (const QString &sourcePath0, const QString &targetPath) -{ - QList copyTasks; - QList linkTasks; - QString sourcePath = d->m_installer->replaceVariables(sourcePath0); - listDir(sourcePath, targetPath, ©Tasks, &linkTasks, d->m_installer); - d->m_tasks += copyTasks; - d->m_tasks += linkTasks; -} - -void QInstallerComponent::appendSettingsTask - (const QString &key, const QString &value) -{ - QInstallerWriteSettingsTask *task = - new QInstallerWriteSettingsTask(d->m_installer); - task->setKey(key); - task->setValue(value); - appendTask(task); -} - -void QInstallerComponent::appendTask(QInstallerTask *task) -{ - d->m_tasks.append(task); -} - -int QInstallerComponent::taskCount() const -{ - return d->m_tasks.size(); -} - -QInstallerTask *QInstallerComponent::task(int i) const -{ - return d->m_tasks.at(i); -} - -//////////////////////////////////////////////////////////////////// -// -// QInstaller::Private -// -//////////////////////////////////////////////////////////////////// - -QInstallerTask *createCopyFileTask(QInstaller *installer) -{ - return new QInstallerCopyFileTask(installer); -} - -QInstallerTask *createLinkFileTask(QInstaller *installer) -{ - return new QInstallerLinkFileTask(installer); -} - -QInstallerTask *createWriteSettingsTask(QInstaller *installer) -{ - return new QInstallerWriteSettingsTask(installer); -} - -QInstallerTask *createPatchFileTask(QInstaller *installer) -{ - return new QInstallerPatchFileTask(installer); -} - -QInstallerTask *createMenuShortcutTask(QInstaller *installer) -{ - return new QInstallerMenuShortcutTask(installer); -} - - - -class QInstaller::Private : public QObject -{ - Q_OBJECT; - -public: - explicit Private(QInstaller *); - ~Private(); - - void initialize(); - - QInstallerTask *createTaskFromCode(int code); - void undo(const QList &tasks); - void writeUninstaller(const QList &tasks); - bool statusCanceledOrFailed() const; - - void writeInstaller(QIODevice *out); - void writeInstaller(); - void appendCode(QIODevice *out); - void runInstaller(); - void runUninstaller(); - void deleteUninstaller(); - QString uninstallerName() const; - QString replaceVariables(const QString &str) const; - QByteArray replaceVariables(const QByteArray &str) const; - QString registerPath() const; - void registerInstaller(); - void unregisterInstaller(); - QString installerBinaryPath() const; - bool isCreator() const; - bool isInstaller() const; - bool isUninstaller() const; - bool isTempUninstaller() const; - QInstaller *installer() const { return q; } - bool restartTempUninstaller(const QStringList &args); - void setInstallationProgress(qint64 progress); // relative to m_totalProgress - -signals: - void installationStarted(); - void installationFinished(); - void uninstallationStarted(); - void uninstallationFinished(); - -public: - QInstaller *q; - - Dictionary m_vars; - QInstaller::InstallerStatus m_status; - bool m_verbose; - - qint64 m_codeSize; - qint64 m_tasksStart; - qint64 m_variablesStart; - qint64 m_componentCount; - qint64 m_tasksOffsetsStart; - qint64 m_variablesOffsetsStart; - qint64 m_variableDataStart; - qint64 m_magicMarker; - - int m_installationProgress; - int m_totalProgress; - QString m_installationProgressText; - - // Owned. Indexed by component name - QList m_components; - QList m_taskCreators; -}; - -QInstaller::Private::Private(QInstaller *q_) - : q(q_), m_status(QInstaller::InstallerUnfinished), m_verbose(false) -{ - connect(this, SIGNAL(installationStarted()), - q, SIGNAL(installationStarted())); - connect(this, SIGNAL(installationFinished()), - q, SIGNAL(installationFinished())); - connect(this, SIGNAL(uninstallationStarted()), - q, SIGNAL(uninstallationStarted())); - connect(this, SIGNAL(uninstallationFinished()), - q, SIGNAL(uninstallationFinished())); -} - -QInstaller::Private::~Private() -{ - qDeleteAll(m_components); - m_components.clear(); -} - - -void QInstaller::Private::initialize() -{ - m_installationProgress = 0; - m_totalProgress = 100; - - m_vars["ProductName"] = "Unknown Product"; - m_vars["LogoPixmap"] = ":/resources/logo.png"; - m_vars["WatermarkPixmap"] = ":/resources/watermark.png"; - - QFile in(installerBinaryPath()); - openForRead(in); - m_codeSize = in.size(); - - // this reads bogus values for 'creators', but it does not harm - in.seek(in.size() - 7 * sizeof(qint64)); - m_tasksStart = retrieveInt(&in); - m_variablesStart = retrieveInt(&in); - m_componentCount = retrieveInt(&in); - m_tasksOffsetsStart = retrieveInt(&in); - m_variablesOffsetsStart = retrieveInt(&in); - m_variableDataStart = retrieveInt(&in); - m_magicMarker = retrieveInt(&in); - - if (isCreator()) { - // valgrind complains otherwise - m_tasksStart = 0; - m_variablesStart = 0; - m_componentCount = 0; - m_tasksOffsetsStart = 0; - m_variablesOffsetsStart = 0; - m_variableDataStart = 0; - m_magicMarker = 0; - } else { - // fix code size - m_codeSize = m_tasksStart; - - // merge stored variables - in.seek(m_variablesStart); - - for (int i = 0; i != m_componentCount; ++i) { - QInstallerComponent *component = new QInstallerComponent(q); - component->d->m_vars = retrieveDictionary(&in); - qDebug() << "DICT " << i << component->d->m_vars; - m_components.append(component); - } - - // read installer variables - Dictionary dict = retrieveDictionary(&in); - if (m_verbose) - qDebug() << "READ VARIABLES FROM INSTALLER:" << dict; - foreach (const QString &key, dict.keys()) { - if (!m_vars.contains(key)) - m_vars.insert(key, dict.value(key)); - } - if (m_verbose) - qDebug() << "MERGED VARIABLES:" << m_vars; - } -} - -void QInstaller::Private::setInstallationProgress(qint64 progress) -{ - // from 0 to m_totalProgress - int percent = progress * 100 / m_totalProgress; - if (percent == m_installationProgress) - return; - //qDebug() << "setting progress to " << progress - // << " of " << m_totalProgress << " " << percent << "%"; - m_installationProgress = percent; - qApp->processEvents(); -} - -QString QInstaller::Private::installerBinaryPath() const -{ - return qApp->arguments().at(0); -} - -bool QInstaller::Private::isCreator() const -{ - return !isInstaller() && !isUninstaller() && !isTempUninstaller(); -} - -bool QInstaller::Private::isInstaller() const -{ - return m_magicMarker == magicInstallerMarker; -} - -bool QInstaller::Private::isUninstaller() const -{ - return m_magicMarker == magicUninstallerMarker; -} - -bool QInstaller::Private::isTempUninstaller() const -{ - return m_magicMarker == magicTempUninstallerMarker; -} - -void QInstaller::Private::writeInstaller() -{ - QString fileName = m_vars["OutputFile"]; -#ifdef Q_OS_WIN - if (!fileName.endsWith(QLatin1String(".exe"))) - fileName += QLatin1String(".exe"); -#endif - QFile out; - out.setFileName(fileName); - openForWrite(out); - writeInstaller(&out); - out.setPermissions(out.permissions() | QFile::WriteUser - | QFile::ExeOther | QFile::ExeGroup | QFile::ExeUser); -} - -void QInstaller::Private::writeInstaller(QIODevice *out) -{ - appendCode(out); - - QList tasksOffsets; - QList variablesOffsets; - - // write component task data - foreach (QInstallerComponent *component, m_components) { - qint64 componentStart = out->size(); - tasksOffsets.append(out->size()); // record start of tasks - // pack the component as a whole - QBuffer buffer; - buffer.open(QIODevice::WriteOnly); - foreach (QInstallerTask *task, component->d->m_tasks) { - appendInt(&buffer, q->indexOfTaskType(task->creator())); - task->writeToInstaller(&buffer); - } - buffer.close(); - QByteArray compressed = qCompress(buffer.buffer()); - int uncompressedSize = buffer.buffer().size(); - int compressedSize = compressed.size(); - appendByteArray(out, compressed); - qDebug() << "COMPRESS: " << uncompressedSize << compressedSize; - component->setValue("TaskCount", QString::number(component->d->m_tasks.size())); - component->setValue("ComponentStart", QString::number(componentStart)); - component->setValue("CompressedSize", QString::number(compressedSize)); - component->setValue("UncompressedSize", QString::number(uncompressedSize)); - } - - // write component variables - foreach (QInstallerComponent *component, m_components) { - variablesOffsets.append(out->size()); // record start of variables - appendDictionary(out, component->d->m_vars); - } - - // append variables except temporary ones - qint64 variableDataStart = out->size(); - Dictionary dict = m_vars; - dict.removeTemporaryKeys(); - appendDictionary(out, dict); - - // append recorded list of component task offsets - qint64 taskOffsetsStart = out->size(); - foreach (qint64 offset, tasksOffsets) - appendInt(out, offset); - - // append recorded list of component varaibles offsets - qint64 variablesOffsetsStart = out->size(); - foreach (qint64 offset, variablesOffsets) - appendInt(out, offset); - - // append trailer - appendInt(out, tasksOffsets[0]); - appendInt(out, variablesOffsets[0]); - appendInt(out, m_components.size()); - appendInt(out, taskOffsetsStart); - appendInt(out, variablesOffsetsStart); - appendInt(out, variableDataStart); - appendInt(out, magicInstallerMarker); -} - -bool QInstaller::Private::statusCanceledOrFailed() const -{ - return m_status == QInstaller::InstallerCanceledByUser - || m_status == QInstaller::InstallerFailed; -} - -QInstallerTask *QInstaller::Private::createTaskFromCode(int code) -{ - if (code >= 0 && code < m_taskCreators.size()) - return m_taskCreators[code](q); - throw Error("NO TASK WITH CODE %1 REGISTERED"); -} - -void QInstaller::Private::undo(const QList &tasks) -{ - //qDebug() << "REMOVING" << files.size(); - // tasks.size() corresponds to m_installationProgress; - m_totalProgress = tasks.size() * m_installationProgress / 100 + 1; - for (int i = tasks.size(); --i >= 0; ) { - QInstallerTask *task = tasks.at(i); - setInstallationProgress(i); - task->undo(); - } - setInstallationProgress(0); -} - -void QInstaller::Private::appendCode(QIODevice *out) -{ - QFile in(installerBinaryPath()); - openForRead(in); - if (m_verbose) - qDebug() << "CODE SIZE: " << m_codeSize; - appendData(out, &in, m_codeSize); - in.close(); -} - -QString QInstaller::Private::replaceVariables(const QString &str) const -{ - QString res; - int pos = 0; - while (true) { - int pos1 = str.indexOf('@', pos); - if (pos1 == -1) - break; - int pos2 = str.indexOf('@', pos1 + 1); - if (pos2 == -1) - break; - res += str.mid(pos, pos1 - pos); - QString name = str.mid(pos1 + 1, pos2 - pos1 - 1); - res += m_vars.value(name); - pos = pos2 + 1; - } - res += str.mid(pos); - return res; -} - -QByteArray QInstaller::Private::replaceVariables(const QByteArray &ba) const -{ - QByteArray res; - int pos = 0; - while (true) { - int pos1 = ba.indexOf('@', pos); - if (pos1 == -1) - break; - int pos2 = ba.indexOf('@', pos1 + 1); - if (pos2 == -1) - break; - res += ba.mid(pos, pos1 - pos); - QString name = QString::fromLocal8Bit(ba.mid(pos1 + 1, pos2 - pos1 - 1)); - res += m_vars.value(name).toLocal8Bit(); - pos = pos2 + 1; - } - res += ba.mid(pos); - return res; -} - -QString QInstaller::Private::uninstallerName() const -{ - QString name = m_vars["TargetDir"]; - name += "/uninstall"; -#ifdef Q_OS_WIN - name += QLatin1String(".exe"); -#endif - return name; -} - -void QInstaller::Private::writeUninstaller(const QList &tasks) -{ - QFile out(uninstallerName()); - try { - ifVerbose("CREATING UNINSTALLER " << tasks.size()); - // Create uninstaller. this is basically a clone of ourselves - // with a few changed variables - openForWrite(out); - appendCode(&out); - qint64 tasksStart = out.size(); - appendInt(&out, tasks.size()); - - for (int i = tasks.size(); --i >= 0; ) { - QInstallerTask *task = tasks.at(i); - appendInt(&out, m_taskCreators.indexOf(task->creator())); - task->writeToUninstaller(&out); // might throw - } - - // append variables except temporary ones - qint64 variableDataStart = out.size(); - Dictionary dict = m_vars; - dict.removeTemporaryKeys(); - dict.setValue(QLatin1String("UninstallerPath"), uninstallerName()); - appendDictionary(&out, dict); - - // append trailer - appendInt(&out, tasksStart); - appendInt(&out, variableDataStart); // variablesStart - appendInt(&out, 0); // componentCount - appendInt(&out, 0); // tasksOffsetsStart - appendInt(&out, 0); // variablesOffsetsStart - appendInt(&out, variableDataStart); - appendInt(&out, magicUninstallerMarker); - - out.setPermissions(out.permissions() | QFile::WriteUser - | QFile::ExeOther | QFile::ExeGroup | QFile::ExeUser); - } - catch (const QInstallerError &err) { - m_status = QInstaller::InstallerFailed; - // local roll back - qDebug() << "WRITING TO UNINSTALLER FAILED: " << err.message(); - out.close(); - out.remove(); - throw; - } -} - -QString QInstaller::Private::registerPath() const -{ - QString productName = m_vars["ProductName"]; - if (productName.isEmpty()) - throw QInstallerError("ProductName should be set"); - QString path; - if (m_vars["AllUsers"] == "true") - path += "HKEY_LOCAL_MACHINE"; - else - path += "HKEY_CURRENT_USER"; - path += "\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"; - path += productName; - return path; -} - -void QInstaller::Private::registerInstaller() -{ -#ifdef Q_OS_WIN - QSettings settings(registerPath(), QSettings::NativeFormat); - settings.beginGroup("CurrentVersion"); - settings.beginGroup("Uninstall"); - settings.beginGroup(m_vars["ProductName"]); - settings.setValue("Comments", m_vars["Comments"]); - settings.setValue("Contact", m_vars["Contact"]); - settings.setValue("DisplayName", m_vars["ProductName"]); - settings.setValue("DisplayVersion", m_vars["DisplayVersion"]); - settings.setValue("EstimatedSize", "X4957efb0"); - settings.setValue("HelpLink", m_vars["HelpLink"]); - settings.setValue("InstallDate", QDateTime::currentDateTime().toString()); - settings.setValue("InstallLocation", m_vars["TargetDir"]); - settings.setValue("NoModify", "1"); - settings.setValue("NoRepair", "1"); - settings.setValue("Publisher", m_vars["Publisher"]); - settings.setValue("UninstallString", uninstallerName()); - settings.setValue("UrlInfoAbout", m_vars["UrlInfoAbout"]); -#endif -} - -void QInstaller::Private::unregisterInstaller() -{ -#ifdef Q_OS_WIN - QSettings settings(registerPath(), QSettings::NativeFormat); - settings.remove(QString()); -#endif -} - -void QInstaller::Private::runInstaller() -{ - QList tasks; - - try { - emit installationStarted(); - if (!m_vars.contains("TargetDir")) - throw QInstallerError(QLatin1String("Variable 'TargetDir' not set.")); - - QFile in(installerBinaryPath()); - openForRead(in); - - m_totalProgress = 0; - QList componentsToInstall; - - for (int i = 0; i != m_componentCount; ++i) { - QInstallerComponent *comp = m_components.at(i); - QString wantedState = comp->value("WantedState"); - ifVerbose("HANDLING COMPONENT" << i << "WANTED: " << wantedState); - if (wantedState == "Uninstalled") { - qDebug() << "SKIPPING COMPONENT" << comp->value("DisplayName"); - continue; - } - componentsToInstall.append(comp); - m_totalProgress += comp->value("UncompressedSize").toInt(); - } - - qDebug() << "Install size: " << m_totalProgress - << "in " << componentsToInstall.size() << "components"; - - qint64 lastProgressBase = 0; - foreach (QInstallerComponent *comp, componentsToInstall) { - int taskCount = comp->value("TaskCount").toInt(); - quint64 componentStart = comp->value("ComponentStart").toInt(); - in.seek(componentStart); - if (statusCanceledOrFailed()) - throw Error("Installation canceled by user"); - m_installationProgressText = - tr("Decompressing component %1").arg(comp->value("DisplayName")); - qApp->processEvents(); - QByteArray compressed = retrieveByteArray(&in); - QByteArray uncompressed = qUncompress(compressed); - if (uncompressed.isEmpty()) { - qDebug() << "SIZE: " << compressed.size() << " TASK COUNT: " << taskCount - << uncompressed.size(); - throw Error("DECOMPRESSION FAILED"); - } - QBuffer buffer(&uncompressed); - buffer.open(QIODevice::ReadOnly); - for (int j = 0; j != taskCount; ++j) { - int code = retrieveInt(&buffer); - QInstallerTask *task = createTaskFromCode(code); // might throw - task->readAndExecuteFromInstaller(&buffer); // might throw - tasks.append(task); - if (statusCanceledOrFailed()) - throw Error("Installation canceled by user"); - setInstallationProgress(lastProgressBase + buffer.pos()); - } - comp->setValue("CurrentState", "Installed"); - lastProgressBase += uncompressed.size(); - } - in.close(); - - registerInstaller(); - writeUninstaller(tasks); - - m_status = InstallerSucceeded; - m_installationProgressText = tr("Installation finished!"); - qApp->processEvents(); - emit installationFinished(); - } - catch (const QInstallerError &err) { - installer()->showWarning(err.message()); - qDebug() << "INSTALLER FAILED: " << err.message() << "\nROLLING BACK"; - undo(tasks); - m_installationProgressText = tr("Installation aborted"); - qApp->processEvents(); - emit installationFinished(); - throw; - } -} - -bool QInstaller::Private::restartTempUninstaller(const QStringList &args) -{ -#ifdef Q_OS_WIN - ifVerbose("Running uninstaller on Windows."); - if (isUninstaller()) { - QString uninstallerFile = installerBinaryPath(); - QDir tmpDir = QDir::temp(); - QString tmpDirName = QLatin1String("qtcreator_uninst"); - QString tmpAppName = QLatin1String("uninst.exe"); - if (!tmpDir.exists(tmpDirName)) { - tmpDir.mkdir(tmpDirName); - if (!tmpDir.exists(tmpDirName)) { - ifVerbose("Could not create temporary folder!"); - return false; - } - tmpDir.cd(tmpDirName); - } - - if (tmpDir.exists(tmpAppName) && !tmpDir.remove(tmpAppName)) { - ifVerbose("Could not remove old temporary uninstaller!"); - return false; - } - - QString tmpUninstaller = tmpDir.absoluteFilePath(tmpAppName); - - QFile in(uninstallerFile); - if (!in.open(QIODevice::ReadOnly)) { - ifVerbose("Cannot open uninstall.exe!"); - return false; - } - - QFile out(tmpUninstaller); - if (!out.open(QIODevice::WriteOnly)) { - ifVerbose("Cannot open temporary uninstall.exe!"); - return false; - } - - QByteArray ba = in.readAll(); - QBuffer buf(&ba); - buf.open(QIODevice::ReadWrite); - buf.seek(buf.size() - sizeof(qint64)); - appendInt(&buf, magicTempUninstallerMarker); - if (in.size() != out.write(buf.data())) { - ifVerbose("Could not copy uninstaller!"); - return false; - } - - in.close(); - out.close(); - - MoveFileExW((TCHAR*)tmpUninstaller.utf16(), - 0, MOVEFILE_DELAY_UNTIL_REBOOT|MOVEFILE_REPLACE_EXISTING); - - STARTUPINFOW sInfo; - PROCESS_INFORMATION pInfo; - memset(&sInfo, 0, sizeof(sInfo)); - memset(&pInfo, 0, sizeof(pInfo)); - sInfo.cb = sizeof(sInfo); - - QString cmd = QString("\"%1\"").arg(tmpUninstaller); - foreach (const QString &s, args) - cmd.append(QLatin1String(" \"") + s + QLatin1String("\"")); - if (CreateProcessW(0, (TCHAR*)cmd.utf16(), 0, 0, false, 0, 0, 0, &sInfo, &pInfo)) { - CloseHandle(pInfo.hThread); - CloseHandle(pInfo.hProcess); - ifVerbose("Started temp uninstaller."); - } else { - ifVerbose("Cannot launch uninstaller!"); - return false; - } - } -#else - Q_UNUSED(args); -#endif - return true; -} - -void QInstaller::Private::runUninstaller() -{ - QFile uninstaller(installerBinaryPath()); - openForRead(uninstaller); - QByteArray ba = uninstaller.readAll(); - uninstaller.close(); - - emit uninstallationStarted(); -#ifndef Q_OS_WIN - // remove uninstaller binary itself. Also necessary for successful - // removal of the application directory. - uninstaller.remove(); -#else - if (m_vars.contains(QLatin1String("UninstallerPath"))) { - QFile orgUninstaller(m_vars.value(QLatin1String("UninstallerPath"))); - orgUninstaller.remove(); - } -#endif - - // read file - QBuffer in(&ba); - in.open(QIODevice::ReadOnly); - in.seek(m_tasksStart); - qint64 taskCount = retrieveInt(&in); - ifVerbose("FOUND " << taskCount << "UNINSTALLER TASKS"); - - m_totalProgress = m_variablesStart; - for (int i = 0; i != taskCount; ++i) { - int code = retrieveInt(&in); - QInstallerTask *task = createTaskFromCode(code); - task->readAndExecuteFromUninstaller(&in); - setInstallationProgress(in.pos()); - } - in.close(); - - unregisterInstaller(); - - m_installationProgressText = tr("Deinstallation finished"); - qApp->processEvents(); - emit uninstallationFinished(); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstaller -// -//////////////////////////////////////////////////////////////////// - -QInstaller::QInstaller() -{ - d = new Private(this); - d->initialize(); - registerTaskType(createCopyFileTask); - registerTaskType(createLinkFileTask); - registerTaskType(createPatchFileTask); - registerTaskType(createWriteSettingsTask); - registerTaskType(createMenuShortcutTask); -} - -QInstaller::~QInstaller() -{ - delete d; -} - -void QInstaller::appendComponent(QInstallerComponent *component) -{ - d->m_components.append(component); -} - -int QInstaller::componentCount() const -{ - return d->m_components.size(); -} - -QInstallerComponent *QInstaller::component(int i) const -{ - return d->m_components.at(i); -} - -void QInstaller::registerTaskType(TaskCreator tc) -{ - d->m_taskCreators.append(tc); -} - -int QInstaller::indexOfTaskType(TaskCreator tc) const -{ - return d->m_taskCreators.indexOf(tc); -} - -QString QInstaller::value(const QString &key, const QString &defaultValue) const -{ - return d->m_vars.value(key, defaultValue); -} - -void QInstaller::setValue(const QString &key, const QString &value) -{ - d->m_vars[key] = value; -} - -bool QInstaller::containsValue(const QString &key) const -{ - return d->m_vars.contains(key); -} - -bool QInstaller::isVerbose() const -{ - return d->m_verbose; -} - -void QInstaller::setVerbose(bool on) -{ - d->m_verbose = on; -} - -QInstaller::InstallerStatus QInstaller::status() const -{ - return d->m_status; -} - -void QInstaller::interrupt() -{ - qDebug() << "INTERRUPT INSTALLER"; - d->m_status = InstallerCanceledByUser; -} - -QString QInstaller::replaceVariables(const QString &str) const -{ - return d->replaceVariables(str); -} - -QByteArray QInstaller::replaceVariables(const QByteArray &ba) const -{ - return d->replaceVariables(ba); -} - -int QInstaller::installationProgress() const -{ - return d->m_installationProgress; -} - -void QInstaller::setInstallationProgressText(const QString &value) -{ - d->m_installationProgressText = value; -} - -QString QInstaller::installationProgressText() const -{ - return d->m_installationProgressText; -} - -QString QInstaller::installerBinaryPath() const -{ - return d->installerBinaryPath(); -} - -bool QInstaller::isCreator() const -{ - return d->isCreator(); -} - -bool QInstaller::isInstaller() const -{ - return d->isInstaller(); -} - -bool QInstaller::isUninstaller() const -{ - return d->isUninstaller(); -} - -bool QInstaller::isTempUninstaller() const -{ - return d->isTempUninstaller(); -} - -bool QInstaller::runInstaller() -{ - try { d->runInstaller(); return true; } catch (...) { return false; } -} - -bool QInstaller::runUninstaller() -{ - try { d->runUninstaller(); return true; } catch (...) { return false; } -} - -void QInstaller::showWarning(const QString &str) -{ - emit warning(str); -} - -void QInstaller::dump() const -{ - qDebug() << "COMMAND LINE VARIABLES:" << d->m_vars; -} - -void QInstaller::appendInt(QIODevice *out, qint64 n) -{ - QT_PREPEND_NAMESPACE(appendInt)(out, n); -} - -void QInstaller::appendString(QIODevice *out, const QString &str) -{ - QT_PREPEND_NAMESPACE(appendString)(out, str); -} - -void QInstaller::appendByteArray(QIODevice *out, const QByteArray &str) -{ - QT_PREPEND_NAMESPACE(appendByteArray)(out, str); -} - -qint64 QInstaller::retrieveInt(QIODevice *in) -{ - return QT_PREPEND_NAMESPACE(retrieveInt)(in); -} - -QString QInstaller::retrieveString(QIODevice *in) -{ - return QT_PREPEND_NAMESPACE(retrieveString)(in); -} - -QByteArray QInstaller::retrieveByteArray(QIODevice *in) -{ - return QT_PREPEND_NAMESPACE(retrieveByteArray)(in); -} - -bool QInstaller::run() -{ - try { - if (isCreator()) { - createTasks(); // implemented in derived classes - d->writeInstaller(); - } else if (isInstaller()) { - d->runInstaller(); - } else if (isUninstaller() || isTempUninstaller()) { - runUninstaller(); - } - return true; - } catch (const QInstallerError &err) { - qDebug() << "Caught Installer Error: " << err.message(); - return false; - } -} - -QString QInstaller::uninstallerName() const -{ - return d->uninstallerName(); -} - -QString QInstaller::libraryName(const QString &baseName, const QString &version) -{ -#ifdef Q_OS_WIN - return baseName + QLatin1String(".dll"); -#elif Q_OS_MAC - return QString("lib%1.dylib").arg(baseName); -#else - return QString("lib%1.so.%2").arg(baseName).arg(version); -#endif -} - -bool QInstaller::restartTempUninstaller(const QStringList &args) -{ - return d->restartTempUninstaller(args); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerTask -// -//////////////////////////////////////////////////////////////////// - -QInstallerTask::QInstallerTask(QInstaller *parent) - : m_installer(parent) -{} - -QInstaller *QInstallerTask::installer() const -{ - return m_installer; -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerCopyFileTask -// -//////////////////////////////////////////////////////////////////// - -QInstaller::TaskCreator QInstallerCopyFileTask::creator() const -{ - return &createCopyFileTask; -} - -void QInstallerCopyFileTask::writeToInstaller(QIODevice *out) const -{ - appendString(out, m_targetPath); - appendInt(out, m_permissions); - QFile file(m_sourcePath); - openForRead(file); - appendFileData(out, &file); -} - -static int createParentDirs(const QString &absFileName) -{ - QFileInfo fi(absFileName); - if (fi.isDir()) - return 0; - QString dirName = fi.path(); - int n = createParentDirs(dirName); - QDir dir(dirName); - dir.mkdir(fi.fileName()); - return n + 1; -} - -void QInstallerCopyFileTask::readAndExecuteFromInstaller(QIODevice *in) -{ - m_targetPath = installer()->replaceVariables(retrieveString(in)); - m_permissions = retrieveInt(in); - ifVerbose("EXECUTE COPY FILE, TARGET " << m_targetPath); - - QString path = QDir::cleanPath(QFileInfo(m_targetPath).absolutePath()); - m_parentDirCount = createParentDirs(path); - QString msg = QInstaller::tr("Copying file %1").arg(m_targetPath); - installer()->setInstallationProgressText(msg); - - QFile file(m_targetPath); - bool res = file.open(QIODevice::WriteOnly); - if (!res) { - // try to make it writeable, and try again - bool res1 = file.setPermissions(file.permissions()|QFile::WriteOwner); - ifVerbose("MAKE WRITABLE: " << res1); - res = file.open(QIODevice::WriteOnly); - } - if (!res) { - // try to remove it, and try again - bool res1 = file.remove(); - ifVerbose("REMOVING FILE: " << res1); - res = file.open(QIODevice::WriteOnly); - } - - if (!res) { - QString msg = QInstaller::tr("The file %1 is not writeable.") - .arg(m_targetPath); - installer()->showWarning(msg); - throw Error(msg); - } - retrieveFileData(&file, in); - QFile::Permissions perms(m_permissions | QFile::WriteOwner); - file.close(); - file.setPermissions(perms); -} - -void QInstallerCopyFileTask::writeToUninstaller(QIODevice *out) const -{ - appendString(out, m_targetPath); - appendInt(out, m_parentDirCount); -} - -void QInstallerCopyFileTask::readAndExecuteFromUninstaller(QIODevice *in) -{ - m_targetPath = retrieveString(in); - m_parentDirCount = retrieveInt(in); - undo(); -} - -void QInstallerCopyFileTask::undo() -{ - ifVerbose("UNLINKING FILE" << m_targetPath << m_parentDirCount); - QString msg = QInstaller::tr("Removing %1").arg(m_targetPath); - installer()->setInstallationProgressText(msg); - - QFileInfo fi(m_targetPath); - QDir dir(fi.path()); - - QFile file(m_targetPath); - bool res = file.remove(); - if (!res) { - // try to make it writeable, and try again - bool res1 = file.setPermissions(file.permissions()|QFile::WriteOwner); - ifVerbose("MAKE WRITABLE: " << res1); - res = file.remove(); - } - - while (res && --m_parentDirCount >= 0) { - QString dirName = dir.dirName(); - dir.cdUp(); - res = dir.rmdir(dirName); - msg = QInstaller::tr("Removing file %1").arg(m_targetPath); - installer()->setInstallationProgressText(msg); - ifVerbose("REMOVING DIR " << dir.path() << dirName << res); - } -} - -void QInstallerCopyFileTask::dump(QDebug & os) const -{ - os << "c|" + sourcePath() + '|' + targetPath(); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerLinkFileTask -// -//////////////////////////////////////////////////////////////////// - -QInstaller::TaskCreator QInstallerLinkFileTask::creator() const -{ - return &createLinkFileTask; -} - -void QInstallerLinkFileTask::writeToInstaller(QIODevice *out) const -{ - appendString(out, m_targetPath); - appendString(out, m_linkTargetPath); - appendInt(out, m_permissions); -} - -void QInstallerLinkFileTask::readAndExecuteFromInstaller(QIODevice *in) -{ - m_targetPath = installer()->replaceVariables(retrieveString(in)); - m_linkTargetPath = installer()->replaceVariables(retrieveString(in)); - m_permissions = retrieveInt(in); - - ifVerbose("LINK " << m_targetPath << " TARGET " << m_linkTargetPath); - - QFile file(m_linkTargetPath); - if (file.link(m_targetPath)) - return; - - // ok. linking failed. try to remove targetPath and link again - bool res1 = QFile::remove(m_targetPath); - ifVerbose("TARGET EXITS, REMOVE: " << m_targetPath << res1); - if (file.link(m_targetPath)) - return; - - // nothing helped. - throw Error(QInstaller::tr("Cannot link file %1 to %2:\n") - .arg(m_linkTargetPath).arg(m_targetPath)); -} - -void QInstallerLinkFileTask::writeToUninstaller(QIODevice *out) const -{ - appendString(out, m_targetPath); -} - -void QInstallerLinkFileTask::readAndExecuteFromUninstaller(QIODevice *in) -{ - m_targetPath = retrieveString(in); - ifVerbose("UNLINKING LINK" << m_targetPath); - undo(); -} - -void QInstallerLinkFileTask::undo() -{ - QFile file(m_targetPath); - file.remove(); -} - -void QInstallerLinkFileTask::dump(QDebug & os) const -{ - os << "l|" + targetPath() + '|' + linkTargetPath(); -} - -//////////////////////////////////////////////////////////////////// -// -// QInstallerWriteSettingsTask -// -//////////////////////////////////////////////////////////////////// - -QInstaller::TaskCreator QInstallerWriteSettingsTask::creator() const -{ - return &createWriteSettingsTask; -} - -void QInstallerWriteSettingsTask::writeToInstaller(QIODevice *out) const -{ - appendString(out, m_key); - appendString(out, m_value); -} - -void QInstallerWriteSettingsTask::readAndExecuteFromInstaller(QIODevice *in) -{ - m_key = installer()->replaceVariables(retrieveString(in)); - m_value = installer()->replaceVariables(retrieveString(in)); - QSettings settings; - settings.setValue(m_key, m_value); -} - -void QInstallerWriteSettingsTask::writeToUninstaller(QIODevice *out) const -{ - appendString(out, m_key); - appendString(out, m_value); -} - -void QInstallerWriteSettingsTask::readAndExecuteFromUninstaller(QIODevice *in) -{ - m_key = installer()->replaceVariables(retrieveString(in)); - m_value = installer()->replaceVariables(retrieveString(in)); - undo(); -} - -void QInstallerWriteSettingsTask::undo() -{ - QSettings settings; - settings.setValue(m_key, QString()); -} - -void QInstallerWriteSettingsTask::dump(QDebug & os) const -{ - os << "s|" + key() + '|' + value(); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerPatchFileTask -// -//////////////////////////////////////////////////////////////////// - -QInstaller::TaskCreator QInstallerPatchFileTask::creator() const -{ - return &createPatchFileTask; -} - -void QInstallerPatchFileTask::writeToInstaller(QIODevice *out) const -{ - appendString(out, m_targetPath); - appendByteArray(out, m_needle); - appendByteArray(out, m_replacement); -} - -void QInstallerPatchFileTask::readAndExecuteFromInstaller(QIODevice *in) -{ - m_targetPath = installer()->replaceVariables(retrieveString(in)); - m_needle = retrieveByteArray(in); - m_replacement = installer()->replaceVariables(retrieveByteArray(in)); - ifVerbose("PATCHING" << m_replacement << m_needle << m_targetPath); - - QFile file; - file.setFileName(m_targetPath); - if (!file.open(QIODevice::ReadWrite)) - throw Error(QInstaller::tr("Cannot open file %1 for reading").arg(file.fileName())); - - uchar *data = file.map(0, file.size()); - if (!data) - throw Error(QInstaller::tr("Cannot map file %1").arg(file.fileName())); - QByteArray ba = QByteArray::fromRawData((const char *)data, file.size()); - int pos = ba.indexOf(m_needle); - if (pos != -1) { - for (int i = m_replacement.size(); --i >= 0; ) - data[pos + i] = m_replacement.at(i); - } - if (!file.unmap(data)) - throw Error(QInstaller::tr("Cannot unmap file %1").arg(file.fileName())); - file.close(); -} - -void QInstallerPatchFileTask::dump(QDebug & os) const -{ - os << "p|" + targetPath() + '|' + needle() + '|' + replacement(); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerMenuShortcutTask -// -// -// Usage: -// -// static const struct -// { -// const char *target; -// const char *linkTarget; -// } menuShortcuts[] = { -// {"Qt Creator by Nokia\\Run Qt Creator", "bin\\qtcreator.exe"}, -// {"Qt Creator by Nokia\\Readme", "readme.txt"}, -// {"Qt Creator by Nokia\\Uninstall", "uninstall.exe"} -// }; -// -// for (int i = 0; i != sizeof(menuShortcuts) / sizeof(menuShortcuts[0]); ++i) { -// QInstallerMenuShortcutTask *task = new QInstallerMenuShortcutTask(this); -// task->setTargetPath(menuShortcuts[i].target); -// task->setLinkTargetPath(QLatin1String("@TargetDir@\\") + menuShortcuts[i].linkTarget); -// } -// -//////////////////////////////////////////////////////////////////// - -QInstaller::TaskCreator QInstallerMenuShortcutTask::creator() const -{ - return &createMenuShortcutTask; -} - -void QInstallerMenuShortcutTask::writeToInstaller(QIODevice *out) const -{ - appendString(out, m_targetPath); - appendString(out, m_linkTargetPath); -} - -void QInstallerMenuShortcutTask::readAndExecuteFromInstaller(QIODevice *in) -{ - m_targetPath = installer()->replaceVariables(retrieveString(in)); - m_linkTargetPath = installer()->replaceVariables(retrieveString(in)); - -#ifdef Q_OS_WIN - QString workingDir = installer()->value(QLatin1String("TargetDir")); - bool res = false; - HRESULT hres; - IShellLink *psl; - bool neededCoInit = false; - - ifVerbose("CREATE MENU SHORTCUT: " << m_targetPath << " TARGET " << m_linkTargetPath); - - if (installer()->value(QLatin1String("AllUsers")) == "true") { - QSettings registry(QLatin1String("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows" - "\\CurrentVersion\\Explorer\\Shell Folders"), QSettings::NativeFormat); - m_startMenuPath = registry.value(QLatin1String("Common Programs"), QString()).toString(); - } else { - QSettings registry(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows" - "\\CurrentVersion\\Explorer\\Shell Folders"), QSettings::NativeFormat); - m_startMenuPath = registry.value(QLatin1String("Programs"), QString()).toString(); - } - if (m_startMenuPath.isEmpty()) { - ifVerbose("CREATE MENU SHORTCUT: Cannot find start menu folder!"); - return; - } - - if (!m_targetPath.isEmpty()) { - if (!m_targetPath.endsWith(QLatin1String(".lnk"))) - m_targetPath.append(QLatin1String(".lnk")); - m_targetPath = m_targetPath.replace('/', '\\'); - int i = m_targetPath.lastIndexOf('\\'); - if (i > -1) { - QDir dir(m_startMenuPath); - if (!dir.exists(m_targetPath.left(i))) - dir.mkpath(m_targetPath.left(i)); - } - - if (m_linkTargetPath.isEmpty()) - return; - - QString trgt = m_linkTargetPath; - if (trgt.startsWith('\"')) { - trgt = trgt.left(trgt.indexOf('\"', 1) + 1); - } else { - trgt = trgt.left(trgt.indexOf(' ')); - } - if (trgt.isEmpty()) - trgt = m_linkTargetPath; - - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - if (hres == CO_E_NOTINITIALIZED) { - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, - (void **)&psl); - } - if (SUCCEEDED(hres)) { - hres = psl->SetPath((wchar_t *)trgt.utf16()); - if (SUCCEEDED(hres)) { - hres = psl->SetArguments((wchar_t *)m_linkTargetPath.mid(trgt.length()).utf16()); - if (SUCCEEDED(hres)) { - hres = psl->SetWorkingDirectory((wchar_t *)workingDir.utf16()); - if (SUCCEEDED(hres)) { - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); - if (SUCCEEDED(hres)) { - hres = ppf->Save((TCHAR*)QString(m_startMenuPath - + QDir::separator() + m_targetPath).utf16(), TRUE); - if (SUCCEEDED(hres)) - res = true; - ppf->Release(); - } - } - } - } - psl->Release(); - } - if (neededCoInit) - CoUninitialize(); - } - if (!res) { - QString msg = QInstaller::tr("Cannot create menu shortcut %1 to %2:\n") - .arg(m_linkTargetPath).arg(m_targetPath); - installer()->showWarning(msg); - return; - } -#endif -} - -void QInstallerMenuShortcutTask::writeToUninstaller(QIODevice *out) const -{ - appendString(out, m_targetPath); - appendString(out, m_startMenuPath); -} - -void QInstallerMenuShortcutTask::readAndExecuteFromUninstaller(QIODevice *in) -{ - m_targetPath = retrieveString(in); - m_startMenuPath = retrieveString(in); - ifVerbose("REMOVE MENU SHORTCUT: " << m_targetPath); - undo(); -} - -void QInstallerMenuShortcutTask::undo() -{ -#ifdef Q_OS_WIN - QFileInfo fi(m_startMenuPath + QDir::separator() + m_targetPath); - QString path = fi.absoluteFilePath(); - if (fi.isFile()) { - path = fi.absolutePath(); - QFile file(fi.absoluteFilePath()); - file.remove(); - } - QDir dir(m_startMenuPath); - dir.rmpath(path); -#endif -} - -void QInstallerMenuShortcutTask::dump(QDebug & os) const -{ - os << "msc|" + targetPath() + '|' + linkTargetPath(); -} - -QT_END_NAMESPACE - -#include "qinstaller.moc" diff --git a/installer/qinstaller.h b/installer/qinstaller.h deleted file mode 100644 index ea3a97f8d51..00000000000 --- a/installer/qinstaller.h +++ /dev/null @@ -1,357 +0,0 @@ -/*************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** -** Non-Open Source Usage -** -** Licensees may use this file in accordance with the Qt Beta Version -** License Agreement, Agreement version 2.2 provided with the Software or, -** alternatively, in accordance with the terms contained in a written -** agreement between you and Nokia. -** -** GNU General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the packaging -** of this file. Please review the following information to ensure GNU -** General Public Licensing requirements will be met: -** -** http://www.fsf.org/licensing/licenses/info/GPLv2.html and -** http://www.gnu.org/copyleft/gpl.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt GPL Exception -** version 1.3, included in the file GPL_EXCEPTION.txt in this package. -** -***************************************************************************/ - -#ifndef QINSTALLER_H -#define QINSTALLER_H - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QIODevice; -class QInstallerTask; -class QInstallerComponent; - -class QInstaller : public QObject -{ - Q_OBJECT - -public: - QInstaller(); - ~QInstaller(); - - bool run(); - - // parameter handling - void setValue(const QString &key, const QString &value); - QString value(const QString &key, - const QString &defaultValue = QString()) const; - bool containsValue(const QString &key) const; - QString replaceVariables(const QString &str) const; - QByteArray replaceVariables(const QByteArray &str) const; - QString installerBinaryPath() const; - QString uninstallerName() const; - - // installer-specific task creation - virtual void createTasks() {} - - // component handling - void appendComponent(QInstallerComponent *components); - int componentCount() const; - QInstallerComponent *component(int i) const; - typedef QInstallerTask *(*TaskCreator)(QInstaller *); - void registerTaskType(TaskCreator); - int indexOfTaskType(TaskCreator) const; - - // progress handling - //void setInstallationProgress(int); - int installationProgress() const; - void setInstallationProgressText(const QString &); - QString installationProgressText() const; - - // convenience - bool isCreator() const; - bool isInstaller() const; - bool isUninstaller() const; - bool isTempUninstaller() const; - - bool isVerbose() const; - void setVerbose(bool on); - void connectGui(QObject *gui); - - QString libraryName(const QString &baseName, const QString &version); - - bool restartTempUninstaller(const QStringList &args); - - // status - enum InstallerStatus { - InstallerUnfinished, - InstallerCanceledByUser, - InstallerFailed, - InstallerSucceeded, - }; - InstallerStatus status() const; - - // I/O helper for authors of classes deriving from QInstallerStep - static void appendInt(QIODevice *out, qint64 n); - static void appendString(QIODevice *out, const QString &str); - static void appendByteArray(QIODevice *out, const QByteArray &str); - static qint64 retrieveInt(QIODevice *in); - static QString retrieveString(QIODevice *in); - static QByteArray retrieveByteArray(QIODevice *in); - - void dump() const; - class Private; - -public slots: - bool runInstaller(); - bool runUninstaller(); - void interrupt(); - void showWarning(const QString &); - -signals: - void installationStarted(); - void installationFinished(); - void uninstallationStarted(); - void uninstallationFinished(); - void warning(QString); - -private: - Private *d; -}; - - -class QInstallerComponent -{ -public: - explicit QInstallerComponent(QInstaller *installer); - ~QInstallerComponent(); - - void setValue(const QString &key, const QString &value); - QString value(const QString &key, - const QString &defaultValue = QString()) const; - - void appendTask(QInstallerTask *step); - void appendDirectoryTasks(const QString &sourcePath, - const QString &targetPath); - void appendSettingsTask(const QString &key, const QString &value); - void appendUninstallerRegistrationTask(); - int taskCount() const; - QInstallerTask *task(int) const; - - friend class QInstaller; - friend class QInstaller::Private; -private: - Q_DISABLE_COPY(QInstallerComponent); - class Private; - Private *d; -}; - - -class QInstallerTask -{ -public: - QInstallerTask(QInstaller *parent); - virtual ~QInstallerTask() {} - - QInstaller *installer() const; - - virtual void writeToInstaller(QIODevice *out) const = 0; - virtual void readAndExecuteFromInstaller(QIODevice *in) = 0; - - virtual void writeToUninstaller(QIODevice *out) const = 0; - virtual void readAndExecuteFromUninstaller(QIODevice *in) = 0; - - virtual void undo() = 0; - virtual void dump(QDebug &) const {} - - virtual QInstaller::TaskCreator creator() const = 0; - -private: - QInstaller *m_installer; -}; - - -class QInstallerError -{ -public: - QInstallerError(const QString &m) : m_message(m) {} - virtual ~QInstallerError() {} - virtual QString message() const { return m_message; } -private: - QString m_message; -}; - -///////////////////////////////////////////////////////////////////// -// -// Some useful examples -// -///////////////////////////////////////////////////////////////////// - - -class QInstallerCopyFileTask : public QInstallerTask -{ -public: - QInstallerCopyFileTask(QInstaller *parent) : QInstallerTask(parent) {} - QInstaller::TaskCreator creator() const; - - void setSourcePath(const QString &sourcePath) { m_sourcePath = sourcePath; } - QString sourcePath() const { return m_sourcePath; } - - void setTargetPath(const QString &targetPath) { m_targetPath = targetPath; } - QString targetPath() const { return m_targetPath; } - - void setPermissions(qint64 permissions) { m_permissions = permissions; } - qint64 permissions() const { return m_permissions; } - - void writeToInstaller(QIODevice *out) const; - void readAndExecuteFromInstaller(QIODevice *in); - - void writeToUninstaller(QIODevice *out) const; - void readAndExecuteFromUninstaller(QIODevice *in); - - void undo(); - void dump(QDebug &) const; - -private: - QString m_sourcePath; - QString m_targetPath; - qint64 m_permissions; - int m_parentDirCount; -}; - - -class QInstallerLinkFileTask : public QInstallerTask -{ -public: - QInstallerLinkFileTask(QInstaller *parent) : QInstallerTask(parent) {} - QInstaller::TaskCreator creator() const; - - void setTargetPath(const QString &path) { m_targetPath = path; } - QString targetPath() const { return m_targetPath; } - - void setLinkTargetPath(const QString &path) { m_linkTargetPath = path; } - QString linkTargetPath() const { return m_linkTargetPath; } - - void setPermissions(qint64 permissions) { m_permissions = permissions; } - qint64 permissions() const { return m_permissions; } - - void writeToInstaller(QIODevice *out) const; - void readAndExecuteFromInstaller(QIODevice *in); - - void writeToUninstaller(QIODevice *out) const; - void readAndExecuteFromUninstaller(QIODevice *in); - - void undo(); - void dump(QDebug &) const; - -public: - QString m_targetPath; // location of the link in the target system - QString m_linkTargetPath; // linkee - qint64 m_permissions; -}; - - -class QInstallerWriteSettingsTask : public QInstallerTask -{ -public: - QInstallerWriteSettingsTask(QInstaller *parent) - : QInstallerTask(parent) {} - QInstaller::TaskCreator creator() const; - - void setKey(const QString &key) { m_key = key; } - QString key() const { return m_key; } - - void setValue(const QString &value) { m_value = value; } - QString value() const { return m_value; } - - void writeToInstaller(QIODevice *out) const; - void readAndExecuteFromInstaller(QIODevice *in); - - void writeToUninstaller(QIODevice *out) const; - void readAndExecuteFromUninstaller(QIODevice *in); - - void undo(); - void dump(QDebug &) const; - -public: - QString m_key; - QString m_value; -}; - - -class QInstallerPatchFileTask : public QInstallerTask -{ -public: - QInstallerPatchFileTask(QInstaller *parent) : QInstallerTask(parent) {} - QInstaller::TaskCreator creator() const; - - void setTargetPath(const QString &path) { m_targetPath = path; } - QString targetPath() const { return m_targetPath; } - - void setNeedle(const QByteArray &needle) { m_needle = needle; } - QByteArray needle() const { return m_needle; } - - void setReplacement(const QByteArray &repl) { m_replacement = repl; } - QByteArray replacement() const { return m_replacement; } - - void writeToInstaller(QIODevice *out) const; - void readAndExecuteFromInstaller(QIODevice *in); - - void writeToUninstaller(QIODevice *) const {} - void readAndExecuteFromUninstaller(QIODevice *) {} - - void undo() {} - void dump(QDebug &) const; - -private: - QByteArray m_needle; - QByteArray m_replacement; - QString m_targetPath; -}; - - -class QInstallerMenuShortcutTask : public QInstallerTask -{ -public: - QInstallerMenuShortcutTask(QInstaller *parent) : QInstallerTask(parent) {} - QInstaller::TaskCreator creator() const; - - void setTargetPath(const QString &path) { m_targetPath = path; } - QString targetPath() const { return m_targetPath; } - - void setLinkTargetPath(const QString &path) { m_linkTargetPath = path; } - QString linkTargetPath() const { return m_linkTargetPath; } - - void writeToInstaller(QIODevice *out) const; - void readAndExecuteFromInstaller(QIODevice *in); - - void writeToUninstaller(QIODevice *out) const; - void readAndExecuteFromUninstaller(QIODevice *in); - - void undo(); - void dump(QDebug &) const; - -public: - QString m_targetPath; - QString m_linkTargetPath; - QString m_startMenuPath; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QINSTALLER_H diff --git a/installer/qinstallergui.cpp b/installer/qinstallergui.cpp deleted file mode 100644 index ca2c6d73c04..00000000000 --- a/installer/qinstallergui.cpp +++ /dev/null @@ -1,742 +0,0 @@ -/*************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** -** Non-Open Source Usage -** -** Licensees may use this file in accordance with the Qt Beta Version -** License Agreement, Agreement version 2.2 provided with the Software or, -** alternatively, in accordance with the terms contained in a written -** agreement between you and Nokia. -** -** GNU General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the packaging -** of this file. Please review the following information to ensure GNU -** General Public Licensing requirements will be met: -** -** http://www.fsf.org/licensing/licenses/info/GPLv2.html and -** http://www.gnu.org/copyleft/gpl.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt GPL Exception -** version 1.3, included in the file GPL_EXCEPTION.txt in this package. -** -***************************************************************************/ - -#include "qinstallergui.h" - -#include "qinstaller.h" -#include "private/qobject_p.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -QT_BEGIN_NAMESPACE - -//////////////////////////////////////////////////////////////////// -// -// QInstallerGui -// -//////////////////////////////////////////////////////////////////// - -QInstallerGui::QInstallerGui(QInstaller *installer, QWidget *parent) - : QWizard(parent) -{ - #ifndef Q_WS_MAC - setWizardStyle(QWizard::ModernStyle); - #endif - setOption(QWizard::IndependentPages); - connect(button(QWizard::CancelButton), SIGNAL(clicked()), - this, SLOT(cancelButtonClicked())); - - connect(this, SIGNAL(interrupted()), - installer, SLOT(interrupt())); - connect(installer, SIGNAL(installationFinished()), - this, SLOT(showFinishedPage())); - connect(installer, SIGNAL(warning(QString)), - this, SLOT(showWarning(QString))); -} - -void QInstallerGui::cancelButtonClicked() -{ - QInstallerPage *page = qobject_cast(currentPage()); - qDebug() << "CANCEL CLICKED" << currentPage() << page; - if (page && page->isInterruptible()) { - QMessageBox::StandardButton bt = QMessageBox::warning(this, - tr("Warning"), - tr("Do you want to abort the installation process?"), - QMessageBox::Yes | QMessageBox::No); - if (bt == QMessageBox::Yes) - emit interrupted(); - } else { - QMessageBox::StandardButton bt = QMessageBox::warning(this, - tr("Warning"), - tr("Do you want to abort the installer application?"), - QMessageBox::Yes | QMessageBox::No); - if (bt == QMessageBox::Yes) - QDialog::reject(); - } -} - -void QInstallerGui::reject() -{} - -void QInstallerGui::showFinishedPage() -{ - qDebug() << "SHOW FINISHED PAGE"; - next(); -} - -void QInstallerGui::showWarning(const QString &msg) -{ - QMessageBox::warning(this, tr("Warning"), msg); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerPage -// -//////////////////////////////////////////////////////////////////// - -QInstallerPage::QInstallerPage(QInstaller *installer) - : m_installer(installer), m_fresh(true) -{ - setSubTitle(QString(" ")); // otherwise the colors will screw up - -} - -QInstaller *QInstallerPage::installer() const -{ - return m_installer; -} - -QPixmap QInstallerPage::watermarkPixmap() const -{ - return QPixmap(m_installer->value("WatermarkPixmap")); -} - -QPixmap QInstallerPage::logoPixmap() const -{ - return QPixmap(m_installer->value("LogoPixmap")); -} - -QString QInstallerPage::productName() const -{ - return m_installer->value("ProductName"); -} - -void QInstallerPage::insertWidget(QWidget *widget, const QString &siblingName, int offset) -{ - QWidget *sibling = findChild(siblingName); - QWidget *parent = sibling ? sibling->parentWidget() : 0; - QLayout *layout = parent ? parent->layout() : 0; - QBoxLayout *blayout = qobject_cast(layout); - //qDebug() << "FOUND: " << sibling << parent << layout << blayout; - if (blayout) { - int index = blayout->indexOf(sibling) + offset; - blayout->insertWidget(index, widget); - } -} - -QWidget *QInstallerPage::findWidget(const QString &objectName) const -{ - return findChild(objectName); -} - -void QInstallerPage::setVisible(bool visible) -{ - QWizardPage::setVisible(visible); - qApp->processEvents(); - //qDebug() << "VISIBLE: " << visible << objectName() << installer(); - if (m_fresh && !visible) { - //qDebug() << "SUPRESSED..."; - m_fresh = false; - return; - } - if (visible) - entering(); - else - leaving(); -} - -int QInstallerPage::nextId() const -{ - //qDebug() << "NEXTID"; - return QWizardPage::nextId(); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerIntroductionPage -// -//////////////////////////////////////////////////////////////////// - -QInstallerIntroductionPage::QInstallerIntroductionPage(QInstaller *installer) - : QInstallerPage(installer) -{ - setObjectName("IntroductionPage"); - setTitle(tr("Setup - %1").arg(productName())); - setPixmap(QWizard::WatermarkPixmap, watermarkPixmap()); - setSubTitle(QString()); - - QLabel *msgLabel = new QLabel(this); - msgLabel->setObjectName("MessageLabel"); - msgLabel->setWordWrap(true); - msgLabel->setText(QInstaller::tr("Welcome to the %1 Setup Wizard.") - .arg(productName())); - - QVBoxLayout *layout = new QVBoxLayout(this); - layout->addWidget(msgLabel); - setLayout(layout); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerLicenseAgreementPage -// -//////////////////////////////////////////////////////////////////// - -QInstallerLicenseAgreementPage::QInstallerLicenseAgreementPage(QInstaller *installer) - : QInstallerPage(installer) -{ - setObjectName("LicenseAgreementPage"); - setTitle(tr("License Agreement")); - QString msg = tr("Please read the following License Agreement. " - "You must accept the terms of this agreement " - "before continuing with the installation."); - setPixmap(QWizard::LogoPixmap, logoPixmap()); - setPixmap(QWizard::WatermarkPixmap, QPixmap()); - - QTextEdit *textEdit = new QTextEdit(this); - textEdit->setObjectName("LicenseText"); - QFile file(":/resources/license.txt"); - file.open(QIODevice::ReadOnly); - textEdit->setText(file.readAll()); - - m_acceptRadioButton = new QRadioButton(tr("I accept the agreement"), this); - m_rejectRadioButton = new QRadioButton(tr("I do not accept the agreement"), this); - - QLabel *msgLabel = new QLabel(msg, this); - msgLabel->setObjectName("MessageLabel"); - msgLabel->setWordWrap(true); - - QVBoxLayout *layout = new QVBoxLayout(this); - layout->addWidget(msgLabel); - layout->addWidget(textEdit); - QHBoxLayout *hlayout = new QHBoxLayout; - hlayout->addWidget(new QLabel(tr("Do you accept this License?"))); - QVBoxLayout *vlayout = new QVBoxLayout; - vlayout->addWidget(m_acceptRadioButton); - vlayout->addWidget(m_rejectRadioButton); - hlayout->addLayout(vlayout); - layout->addLayout(hlayout); - setLayout(layout); - connect(m_acceptRadioButton, SIGNAL(toggled(bool)), - this, SIGNAL(completeChanged())); - connect(m_rejectRadioButton, SIGNAL(toggled(bool)), - this, SIGNAL(completeChanged())); -} - -bool QInstallerLicenseAgreementPage::isComplete() const -{ - return m_acceptRadioButton->isChecked(); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerComponentSelectionPage -// -//////////////////////////////////////////////////////////////////// - -static QString niceSizeText(const QString &str) -{ - qint64 size = str.toInt(); - QString msg = QInstallerComponentSelectionPage::tr( - "This component will occupy approximately %1 %2 on your harddisk."); - if (size < 10000) - return msg.arg(size).arg("Bytes"); - if (size < 1024 * 10000) - return msg.arg(size / 1024).arg("kBytes"); - return msg.arg(size / 1024 / 1024).arg("MBytes"); -} - -class QInstallerComponentSelectionPage::Private : public QObject -{ - Q_OBJECT - -public: - Private(QInstallerComponentSelectionPage *q_, QInstaller *installer) - : q(q_), m_installer(installer) - { - m_treeView = new QTreeWidget(q); - m_treeView->setObjectName("TreeView"); - m_treeView->setMouseTracking(true); - m_treeView->header()->hide(); - - for (int i = 0; i != installer->componentCount(); ++i) { - QInstallerComponent *component = installer->component(i); - QTreeWidgetItem *item = new QTreeWidgetItem(m_treeView); - item->setText(0, component->value("Name")); - item->setToolTip(0, component->value("Description")); - item->setToolTip(1, niceSizeText(component->value("UncompressedSize"))); - //QString current = component->value("CurrentState"); - QString suggested = component->value("SuggestedState"); - if (suggested == "Uninstalled") { - item->setCheckState(0, Qt::Unchecked); - } else if (suggested == "AlwaysInstalled") { - item->setCheckState(0, Qt::PartiallyChecked); - item->setFlags(item->flags() & ~Qt::ItemIsUserCheckable); - } else { //if (suggested == "Installed") - item->setCheckState(0, Qt::Checked); - } - } - - m_descriptionLabel = new QLabel(q); - m_descriptionLabel->setWordWrap(true); - - m_sizeLabel = new QLabel(q); - m_sizeLabel->setWordWrap(true); - - QVBoxLayout *layout = new QVBoxLayout(q); - //layout->addWidget(msgLabel); - QHBoxLayout *hlayout = new QHBoxLayout; - hlayout->addWidget(m_treeView, 3); - QVBoxLayout *vlayout = new QVBoxLayout; - vlayout->addWidget(m_descriptionLabel); - vlayout->addWidget(m_sizeLabel); - vlayout->addSpacerItem(new QSpacerItem(1, 1, - QSizePolicy::MinimumExpanding, - QSizePolicy::MinimumExpanding)); - hlayout->addLayout(vlayout, 2); - layout->addLayout(hlayout); - q->setLayout(layout); - - connect(m_treeView, - SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), - this, SLOT(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); - } - -public slots: - void currentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *) - { - m_descriptionLabel->setText(item->toolTip(0)); - m_sizeLabel->setText(item->toolTip(1)); - } - -public: - QInstallerComponentSelectionPage *q; - QInstaller *m_installer; - QTreeWidget *m_treeView; - QLabel *m_descriptionLabel; - QLabel *m_sizeLabel; -}; - - -QInstallerComponentSelectionPage::QInstallerComponentSelectionPage - (QInstaller *installer) - : QInstallerPage(installer), d(new Private(this, installer)) -{ - setObjectName("ComponentSelectionPage"); - setTitle(tr("Select Components")); - QString msg = tr("Please select the components you want to install."); - setSubTitle(msg); - setPixmap(QWizard::LogoPixmap, logoPixmap()); - setPixmap(QWizard::WatermarkPixmap, QPixmap()); -} - -QInstallerComponentSelectionPage::~QInstallerComponentSelectionPage() -{ - delete d; -} - -void QInstallerComponentSelectionPage::leaving() -{ - int n = d->m_treeView->topLevelItemCount(); - for (int i = 0; i != n; ++i) { - QTreeWidgetItem *item = d->m_treeView->topLevelItem(i); - QInstallerComponent *component = installer()->component(i); - if (item->checkState(0) == Qt::Unchecked) - component->setValue("WantedState", "Uninstalled"); - else - component->setValue("WantedState", "Installed"); - } -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerTargetDirectoryPage -// -//////////////////////////////////////////////////////////////////// - -QInstallerTargetDirectoryPage::QInstallerTargetDirectoryPage(QInstaller *installer) - : QInstallerPage(installer) -{ - setObjectName("TargetDirectoryPage"); - setTitle(tr("Installation Directory")); - setPixmap(QWizard::LogoPixmap, logoPixmap()); - setPixmap(QWizard::WatermarkPixmap, QPixmap()); - - QLabel *msgLabel = new QLabel(this); - msgLabel->setText(QInstaller::tr("Please specify the directory where %1 " - "will be installed.").arg(productName())); - msgLabel->setWordWrap(true); - msgLabel->setObjectName("MessageLabel"); - - m_lineEdit = new QLineEdit(this); - m_lineEdit->setObjectName("LineEdit"); - - QPushButton *browseButton = new QPushButton(this); - browseButton->setObjectName("BrowseButton"); - browseButton->setText("Browse..."); - browseButton->setIcon(QIcon(logoPixmap())); - - QVBoxLayout *layout = new QVBoxLayout(this); - layout->addWidget(msgLabel); - QHBoxLayout *hlayout = new QHBoxLayout; - hlayout->addWidget(m_lineEdit); - hlayout->addWidget(browseButton); - layout->addLayout(hlayout); - setLayout(layout); - - QString targetDir = installer->value("TargetDir"); - //targetDir = QDir::currentPath(); - if (targetDir.isEmpty()) - targetDir = QDir::homePath() + QDir::separator() + productName(); - m_lineEdit->setText(targetDir); - - connect(browseButton, SIGNAL(clicked()), - this, SLOT(dirRequested())); - connect(m_lineEdit, SIGNAL(textChanged(QString)), - this, SIGNAL(completeChanged())); -} - -QString QInstallerTargetDirectoryPage::targetDir() const -{ - return m_lineEdit->text(); -} - -void QInstallerTargetDirectoryPage::setTargetDir(const QString &dirName) -{ - m_lineEdit->setText(dirName); -} - -void QInstallerTargetDirectoryPage::entering() -{ - connect(wizard(), SIGNAL(customButtonClicked(int)), - this, SLOT(targetDirSelected())); -} - -void QInstallerTargetDirectoryPage::leaving() -{ - installer()->setValue("TargetDir", targetDir()); - disconnect(wizard(), SIGNAL(customButtonClicked(int)), - this, SLOT(targetDirSelected())); -} - -void QInstallerTargetDirectoryPage::targetDirSelected() -{ - //qDebug() << "TARGET DIRECTORY"; - QDir dir(targetDir()); - if (dir.exists() && dir.isReadable()) { - QMessageBox::StandardButton bt = QMessageBox::warning(this, - tr("Warning"), - tr("The directory you slected exists already.\n" - "Do you want to continue?"), - QMessageBox::Yes | QMessageBox::No); - if (bt == QMessageBox::Yes) - wizard()->next(); - return; - } - dir.cdUp(); - if (dir.exists() && dir.isReadable()) { - wizard()->next(); - return; - } - wizard()->next(); -} - -void QInstallerTargetDirectoryPage::dirRequested() -{ - //qDebug() << "DIR REQUESTED"; - QString newDirName = QFileDialog::getExistingDirectory(this, - tr("Select Installation Directory"), targetDir() - /*, Options options = ShowDirsOnly*/); - if (newDirName.isEmpty() || newDirName == targetDir()) - return; - m_lineEdit->setText(newDirName); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerReadyForInstallationPage -// -//////////////////////////////////////////////////////////////////// - -QInstallerReadyForInstallationPage:: - QInstallerReadyForInstallationPage(QInstaller *installer) - : QInstallerPage(installer) -{ - setObjectName("ReadyForInstallationPage"); - setTitle(tr("Ready to Install")); - setCommitPage(true); - setButtonText(QWizard::CommitButton, tr("Install")); - - QLabel *msgLabel = new QLabel(this); - msgLabel->setObjectName("MessageLabel"); - msgLabel->setText(QInstaller::tr("Setup is now ready to begin installing %1 " - "on your computer.").arg(productName())); - - QLayout *layout = new QVBoxLayout(this); - layout->addWidget(msgLabel); - setLayout(layout); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerPerformInstallationPage -// -//////////////////////////////////////////////////////////////////// - -QInstallerPerformInstallationPage::QInstallerPerformInstallationPage(QInstaller *gui) - : QInstallerPage(gui) -{ - setObjectName("InstallationPage"); - setTitle(tr("Installing %1").arg(installer()->value("ProductName"))); - setCommitPage(true); - - m_progressBar = new QProgressBar(this); - m_progressBar->setObjectName("ProgressBar"); - m_progressBar->setRange(1, 100); - - m_progressLabel = new QLabel(this); - m_progressLabel->setObjectName("ProgressLabel"); - - m_updateTimer = new QTimer(this); - connect(m_updateTimer, SIGNAL(timeout()), - this, SLOT(updateProgress())); - m_updateTimer->setInterval(50); - - QLayout *layout = new QVBoxLayout(this); - layout->addWidget(m_progressBar); - layout->addWidget(m_progressLabel); - setLayout(layout); - - connect(installer(), SIGNAL(installationStarted()), - this, SLOT(installationStarted())); - connect(installer(), SIGNAL(installationFinished()), - this, SLOT(installationFinished())); -} - -void QInstallerPerformInstallationPage::initializePage() -{ - QWizardPage::initializePage(); - QTimer::singleShot(30, installer(), SLOT(runInstaller())); -} - -// FIXME: remove function -bool QInstallerPerformInstallationPage::isComplete() const -{ - return true; -} - -void QInstallerPerformInstallationPage::installationStarted() -{ - qDebug() << "INSTALLATION STARTED"; - m_updateTimer->start(); - updateProgress(); -} - -void QInstallerPerformInstallationPage::installationFinished() -{ - qDebug() << "INSTALLATION FINISHED"; - m_updateTimer->stop(); - updateProgress(); -} - -void QInstallerPerformInstallationPage::updateProgress() -{ - int progress = installer()->installationProgress(); - if (progress != m_progressBar->value()) - m_progressBar->setValue(progress); - QString progressText = installer()->installationProgressText(); - if (progressText != m_progressLabel->text()) - m_progressLabel->setText(progressText); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerPerformUninstallationPage -// -//////////////////////////////////////////////////////////////////// - -QInstallerPerformUninstallationPage::QInstallerPerformUninstallationPage - (QInstaller *gui) - : QInstallerPage(gui) -{ - setObjectName("UninstallationPage"); - setTitle(tr("Uninstalling %1").arg(installer()->value("ProductName"))); - setCommitPage(true); - - m_progressBar = new QProgressBar(this); - m_progressBar->setObjectName("ProgressBar"); - m_progressBar->setRange(1, 100); - - m_progressLabel = new QLabel(this); - m_progressLabel->setObjectName("ProgressLabel"); - - m_updateTimer = new QTimer(this); - connect(m_updateTimer, SIGNAL(timeout()), - this, SLOT(updateProgress())); - m_updateTimer->setInterval(50); - - QLayout *layout = new QVBoxLayout(this); - layout->addWidget(m_progressBar); - layout->addWidget(m_progressLabel); - setLayout(layout); - - connect(installer(), SIGNAL(uninstallationStarted()), - this, SLOT(uninstallationStarted())); - connect(installer(), SIGNAL(uninstallationFinished()), - this, SLOT(uninstallationFinished())); -} - -void QInstallerPerformUninstallationPage::initializePage() -{ - QWizardPage::initializePage(); - QTimer::singleShot(30, installer(), SLOT(runUninstaller())); -} - -// FIXME: remove function -bool QInstallerPerformUninstallationPage::isComplete() const -{ - return true; -} - -void QInstallerPerformUninstallationPage::uninstallationStarted() -{ - m_updateTimer->start(); - updateProgress(); -} - -void QInstallerPerformUninstallationPage::uninstallationFinished() -{ - m_updateTimer->stop(); - updateProgress(); -} - -void QInstallerPerformUninstallationPage::updateProgress() -{ - int progress = installer()->installationProgress(); - if (progress != m_progressBar->value()) - m_progressBar->setValue(progress); - QString progressText = installer()->installationProgressText(); - if (progressText != m_progressLabel->text()) - m_progressLabel->setText(progressText); -} - - -//////////////////////////////////////////////////////////////////// -// -// QInstallerFinishedPage -// -//////////////////////////////////////////////////////////////////// - -QInstallerFinishedPage::QInstallerFinishedPage(QInstaller *installer) - : QInstallerPage(installer) -{ - setObjectName("FinishedPage"); - setTitle(tr("Completing the %1 Setup Wizard").arg(productName())); - setPixmap(QWizard::WatermarkPixmap, watermarkPixmap()); - setSubTitle(QString()); - - QLabel *msgLabel = new QLabel(this); - msgLabel->setObjectName("MessageLabel"); - msgLabel->setWordWrap(true); - msgLabel->setText(tr("Click Finish to exit the Setup Wizard")); - - m_runItCheckBox = new QCheckBox(this); - m_runItCheckBox->setObjectName("RunItCheckBox"); - m_runItCheckBox->setChecked(true); - - QVBoxLayout *layout = new QVBoxLayout(this); - layout->addWidget(msgLabel); - if (m_runItCheckBox) - layout->addWidget(m_runItCheckBox); - setLayout(layout); -} - -void QInstallerFinishedPage::entering() -{ - qDebug() << "FINISHED ENTERING: "; - connect(wizard()->button(QWizard::FinishButton), SIGNAL(clicked()), - this, SLOT(handleFinishClicked())); - if (installer()->status() == QInstaller::InstallerSucceeded) { - m_runItCheckBox->show(); - m_runItCheckBox->setText(tr("Run %1 now.").arg(productName())); - } else { - setTitle(tr("The %1 Setup Wizard failed").arg(productName())); - m_runItCheckBox->hide(); - m_runItCheckBox->setChecked(false); - } -} - -void QInstallerFinishedPage::leaving() -{ - disconnect(wizard(), SIGNAL(customButtonClicked(int)), - this, SLOT(handleFinishClicked())); -} - -void QInstallerFinishedPage::handleFinishClicked() -{ - if (!m_runItCheckBox->isChecked()) - return; - QString program = installer()->value("RunProgram"); - if (program.isEmpty()) - return; - program = installer()->replaceVariables(program); - qDebug() << "STARTING " << program; - QProcess *process = new QProcess; - process->start(program); - process->waitForFinished(); -} - -#include "qinstallergui.moc" - -QT_END_NAMESPACE diff --git a/installer/qinstallergui.h b/installer/qinstallergui.h deleted file mode 100644 index ec7db64677c..00000000000 --- a/installer/qinstallergui.h +++ /dev/null @@ -1,256 +0,0 @@ -/*************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** -** Non-Open Source Usage -** -** Licensees may use this file in accordance with the Qt Beta Version -** License Agreement, Agreement version 2.2 provided with the Software or, -** alternatively, in accordance with the terms contained in a written -** agreement between you and Nokia. -** -** GNU General Public License Usage -** -** Alternatively, this file may be used under the terms of the GNU General -** Public License versions 2.0 or 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the packaging -** of this file. Please review the following information to ensure GNU -** General Public Licensing requirements will be met: -** -** http://www.fsf.org/licensing/licenses/info/GPLv2.html and -** http://www.gnu.org/copyleft/gpl.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt GPL Exception -** version 1.3, included in the file GPL_EXCEPTION.txt in this package. -** -***************************************************************************/ - -#ifndef QINSTALLERGUI_H -#define QINSTALLERGUI_H - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -class QInstaller; - -// FIXME: move to private classes -class QCheckBox; -class QLabel; -class QLineEdit; -class QProgressBar; -class QRadioButton; -class QTreeView; -class QTreeWidget; - -class QInstallerGui : public QWizard -{ - Q_OBJECT - -public: - explicit QInstallerGui(QInstaller *installer, QWidget *parent = 0); - -signals: - void interrupted(); - -public slots: - void cancelButtonClicked(); - void reject(); - void showFinishedPage(); - void showWarning(const QString &msg); -}; - - -class QInstallerPage : public QWizardPage -{ - Q_OBJECT - -public: - QInstallerPage(QInstaller *installer); - - virtual bool isInterruptible() const { return false; } - virtual QPixmap watermarkPixmap() const; - virtual QPixmap logoPixmap() const; - virtual QString productName() const; - -protected: - QInstaller *installer() const; - - // Inserts widget into the same layout like a sibling identified - // by its name. Default position is just behind the sibling. - virtual void insertWidget(QWidget *widget, const QString &siblingName, - int offset = 1); - virtual QWidget *findWidget(const QString &objectName) const; - - virtual void setVisible(bool visible); // reimp - virtual int nextId() const; // reimp - - virtual void entering() {} // called on entering - virtual void leaving() {} // called on leaving - - virtual void forward() const {} // called when going forwards - //virtual void backward() const {} // called when going back - bool isConstructing() const { return m_fresh; } - -private: - QInstaller *m_installer; - bool m_fresh; -}; - - -class QInstallerIntroductionPage : public QInstallerPage -{ -public: - explicit QInstallerIntroductionPage(QInstaller *installer); -}; - - -class QInstallerLicenseAgreementPage : public QInstallerPage -{ - Q_OBJECT - -public: - explicit QInstallerLicenseAgreementPage(QInstaller *installer); - bool isComplete() const; - -private: - QRadioButton *m_acceptRadioButton; - QRadioButton *m_rejectRadioButton; -}; - - -class QInstallerComponentSelectionPage : public QInstallerPage -{ - Q_OBJECT - -public: - explicit QInstallerComponentSelectionPage(QInstaller *installer); - ~QInstallerComponentSelectionPage(); - -protected: - //void entering(); - void leaving(); - -private: - class Private; - Private *d; -}; - - -class QInstallerTargetDirectoryPage : public QInstallerPage -{ - Q_OBJECT - -public: - explicit QInstallerTargetDirectoryPage(QInstaller *installer); - QString targetDir() const; - void setTargetDir(const QString &dirName); - -protected: - void entering(); - void leaving(); - -private slots: - void targetDirSelected(); - void dirRequested(); - -private: - QLineEdit *m_lineEdit; -}; - - -class QInstallerReadyForInstallationPage : public QInstallerPage -{ - Q_OBJECT - -public: - explicit QInstallerReadyForInstallationPage(QInstaller *installer); -}; - - -class QInstallerPerformInstallationPage : public QInstallerPage -{ - Q_OBJECT - -public: - explicit QInstallerPerformInstallationPage(QInstaller *installer); - -protected: - void initializePage(); - bool isComplete() const; - bool isInterruptible() const { return true; } - -signals: - void installationRequested(); - -private slots: - void installationStarted(); - void installationFinished(); - void updateProgress(); - -private: - QProgressBar *m_progressBar; - QLabel *m_progressLabel; - QTimer *m_updateTimer; -}; - - -class QInstallerPerformUninstallationPage : public QInstallerPage -{ - Q_OBJECT - -public: - explicit QInstallerPerformUninstallationPage(QInstaller *installer); - -protected: - void initializePage(); - bool isComplete() const; - bool isInterruptible() const { return true; } - -signals: - void uninstallationRequested(); - -private slots: - void uninstallationStarted(); - void uninstallationFinished(); - void updateProgress(); - -private: - QProgressBar *m_progressBar; - QLabel *m_progressLabel; - QTimer *m_updateTimer; -}; - - -class QInstallerFinishedPage : public QInstallerPage -{ - Q_OBJECT - -public: - explicit QInstallerFinishedPage(QInstaller *installer); - -public slots: - void handleFinishClicked(); - -protected: - void entering(); - void leaving(); - -private: - QCheckBox *m_runItCheckBox; -}; - - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QINSTALLERGUI_H diff --git a/installer/resources/license.txt b/installer/resources/license.txt deleted file mode 100644 index a55990fe3a0..00000000000 --- a/installer/resources/license.txt +++ /dev/null @@ -1,84 +0,0 @@ -For individuals and/or legal entities resident in the American Continent (including those resident in Canada, South America, and the United States of America), the applicable licensing terms are specified under the heading "Trolltech Technology Preview License -Agreement: American Continent". - -For individuals and/or legal entities not resident in the American Continent, the applicable licensing terms are specified under the heading "Trolltech Technology Preview License Agreement: Norway". - -TROLLTECH TECHNOLOGY PREVIEW LICENSE AGREEMENT: AMERICAN CONTINENT Agreement version 2.0 -IMPORTANT-READ CAREFULLY: - -1. This Trolltech Technology Preview License Agreement ("Agreement") is a legal agreement between you (either an individual or a legal entity) and Trolltech, Inc. ("Trolltech"), and pertains to the Trolltech software product(s) accompanying this Agreement, which include(s) computer software and may include "online" or electronic documentation, associated media, and printed materials, including the source code, example programs and the documentation ("Licensed Software"). - -2. The Licensed Software is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. Trolltech retains all rights not expressly granted. No title, property rights or copyright in the Licensed Software or in any modifications to the Licensed Software shall pass to the Licensee under any circumstances. The Licensed Software is licensed, not sold. - -3. By installing, copying, or otherwise using the Licensed Software, Licensee agrees to be bound by the terms of this Agreement. If Licensee does not agree to the terms of this Agreement, Licensee should not install, copy, or otherwise use the Licensed Software. - -4. Upon Licensee's acceptance of the terms and conditions of this Agreement, Trolltech grants Licensee the right to use the Licensed Software in the manner provided below. - -5. Trolltech grants to Licensee as an individual a personal, non-exclusive, non-transferable license to make and use copies of the Licensed Software for the sole purpose of evaluating and testing the Licensed Software and/or providing feedback to Trolltech. Licensee may install copies of the Licensed Software on an unlimited number of computers provided that Licensee is the only individual using the Licensed Software. If Licensee is an entity, Trolltech grants Licensee the right to designate one, and only one, individual within Licensee's organization who shall have the sole right to use the Licensed Software in the manner provided in this Agreement. Licensee may, at any time, but not more frequently than once every six (6) months, designate another individual to replace the current designated user by notifying Trolltech, so long as there is no more than one (1) designated user at any given time - -6. Licensee may not loan, rent, lease, or license the Licensed Software or any copy of it. Licensee may not alter or remove any details of ownership, copyright, trademark or other property right connected with the Licensed Software. Licensee may not modify or distribute the Licensed Software. Licensee may not distribute any software statically or dynamically linked with the Licensed Software. - -7. This Licensed Software is time-limited. All rights granted to Licensee in this Agreement will be void three (3) months after Licensee received the Licensed Software. - -8. The Licensed Software may provide links to third party libraries or code (collectively "Third Party Libraries") to implement various functions. Third Party Libraries do not comprise part of the Licensed Software. In some cases, access to Third Party Libraries may be included along with the Licensed Software delivery as a convenience for development and testing only. Such source code and libraries as are or may be listed in the ".../src/3rdparty" source tree delivered with the Licensed Software, as may be amended from time to time, do not comprise the Licensed Software. Licensee acknowledges (1) that some Third Party Libraries may require additional licensing of copyright and patents from the owners of such, and (2) that distribution of any of the Licensed Software referencing any portion of a Third Party Library may require appropriate licensing from such third parties. - -9. Pre-Release Code, Non-Commercial Use: The Licensed Software contains Pre-release Code that is not at the level of performance and compatibility of a final, generally available, product offering. The Licensed Software may not operate correctly and may be substantially modified prior to the first commercial shipment, if any. Trolltech is not obligated to make this or any later version of the Licensed Software commercially available. The License Software is "Not for Commercial Use" and may only be used for the purposes described in Section 5. You may not use the Licensed Software in a live operating environment where it may be relied upon to perform in the same manner as a commercially released product or with data that has not been sufficiently backed up. - -10. WARRANTY DISCLAIMER: THE LICENSED SOFTWARE IS LICENSED TO LICENSEE "AS IS". TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, TROLLTECH ON BEHALF OF ITSELF AND ITS SUPPLIERS, DISCLAIMS ALL WARRANTIES AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT WITH REGARD TO THE LICENSED SOFTWARE. - -11. LIMITATION OF LIABILITY: IF, TROLLTECH'S WARRANTY DISCLAIMER NOTWITHSTANDING, TROLLTECH IS HELD LIABLE TO LICENSEE, WHETHER IN CONTRACT, TORT OR ANY OTHER LEGAL THEORY, BASED ON THE LICENSED SOFTWARE, TROLLTECH'S ENTIRE LIABILITY TO LICENSEE AND LICENSEE'S EXCLUSIVE REMEDY SHALL BE, AT TROLLTECH'S OPTION, EITHER (A) RETURN OF THE PRICE LICENSEE PAID FOR THE LICENSED SOFTWARE, OR (B) REPAIR OR REPLACEMENT OF THE LICENSED SOFTWARE, PROVIDED LICENSEE RETURNS TO TROLLTECH ALL COPIES OF THE LICENSED SOFTWARE AS ORIGINALLY DELIVERED TO LICENSEE. TROLLTECH SHALL NOT UNDER ANY CIRCUMSTANCES BE LIABLE TO LICENSEE BASED ON FAILURE OF THE LICENSED SOFTWARE IF THE FAILURE RESULTED FROM ACCIDENT, ABUSE OR MISAPPLICATION, NOR SHALL TROLLTECH UNDER ANY CIRCUMSTANCES BE LIABLE FOR SPECIAL DAMAGES, PUNITIVE OR EXEMPLARY DAMAGES, DAMAGES FOR LOSS OF PROFITS OR INTERRUPTION OF BUSINESS OR FOR LOSS OR CORRUPTION OF DATA. ANY AWARD OF DAMAGES FROM TROLLTECH TO LICENSEE SHALL NOT EXCEED THE TOTAL AMOUNT LICENSEE HAS PAID TO TROLLTECH IN CONNECTION WITH THIS AGREEMENT. - -12. Termination: Without prejudice to any other rights, Trolltech may terminate this Agreement if Licensee fails to comply with the terms and conditions of this Agreement. In such event, Licensee must destroy all copies of the Licensed Software and all of its components. - -13. Export Restrictions: Licensee agrees not to export or re-export the Licensed Software, any part thereof, or any process or service that is the direct product of the Licensed Software. Licensee may not sell, resell, or otherwise transfer for value, the Licensed Software (the foregoing collectively referred to as the "Restricted Components"), to any country, person, entity or end user subject to U.S. export restrictions. Licensee specifically agrees not to export or re-export any of the Restricted Components (i) to any country to which the U.S. has embargoed or restricted the export of goods or services, which currently include, but are not necessarily limited to Cuba, Iran, Iraq, Libya, North Korea, Sudan and Syria, or to any national of any such country, wherever located, who intends to transmit or transport the Restricted Components back to such country; (ii) to any end-user who Licensee knows or has reason to know will utilize the Restricted Components in the design, development or production of nuclear, chemical or biological weapons; or (iii) to any end-user who has been prohibited from participating in U.S. export transactions by any federal agency of the U.S. government. Licensee warrants and represents that neither the U.S. Commerce Department, Bureau of Export Administration nor any other U.S. federal agency has suspended, revoked or denied Licensee's export privileges. - -14. Government End Users: A "U.S. Government End User" shall mean any agency or entity of the government of the United States. The following shall apply if Licensee is a U.S. Government End User. The Licensed Software is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire the Licensed Software with only those rights set forth herein. The Licensed Software (including related documentation) is provided to U.S. Government End Users: (a) only as a commercial end item; and (b) only pursuant to this Agreement. - -15. Compliance with local laws: Licensee shall comply with all applicable laws and regulations relating to the Licensed Software in the United States and in other countries in which Licensee uses or modifies the Licensed Software. Without limiting the generality of the foregoing, Licensee shall not export, re-export, disclose or distribute any of the Licensed Software in violation of any applicable laws or regulations, including the export laws and regulations of the United States, and shall comply with all such laws and regulations. - -16. Entire Agreement: This Agreement constitutes the complete agreement between the parties and supersedes all prior or contemporaneous discussions, representations, and proposals, written or oral, with respect to the subject matters discussed herein. No modification of this Agreement will be effective unless contained in a writing executed by an authorized representative of each party. No term or condition contained in Licensee's purchase order will apply unless expressly accepted by Trolltech in writing. If any provision of the Agreement is found void or unenforceable, the remainder will remain valid and enforceable according to its terms. If any remedy provided is determined to have failed for its essential purpose, all limitations of liability and exclusions of damages set forth in this Agreement shall remain in effect. - -17. Governing law, legal venue: This Agreement shall be construed, interpreted and governed by the laws of the State of California, USA. Any action or proceeding arising from or relating to this Agreement shall be brought in a federal court in the Northern District of California or in the State Court in Santa Clara County, California, and each party irrevocably submits to the personal jurisdiction of any such court in any such action or proceeding. The Agreement gives Licensee specific legal rights; Licensee may have others, which vary from state to state and from country to country. Trolltech reserves all rights not specifically granted in this Agreement. - - - - -For legal entities and/or individuals residing in any country other than Canada, the United States of America or South America: -TROLLTECH TECHNOLOGY PREVIEW LICENSE AGREEMENT: NORWAY - -Agreement version 2.0 -IMPORTANT-READ CAREFULLY: - -1. This Trolltech Technology Preview License Agreement ("Agreement") is a legal agreement between you (either an individual or a legal entity) and Trolltech ASA ("Trolltech"), and pertains to the Trolltech software product(s) accompanying this Agreement, which include(s) computer software and may include "online" or electronic documentation, associated media, and printed materials, including the source code, example programs and the documentation ("Licensed Software"). - -2. The Licensed Software is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. Trolltech retains all rights not expressly granted. No title, property rights or copyright in the Licensed Software or in any modifications to the Licensed Software shall pass to the Licensee under any circumstances. The Licensed Software is licensed, not sold. - -3. By installing, copying, or otherwise using the Licensed Software, Licensee agrees to be bound by the terms of this Agreement. If Licensee does not agree to the terms of this Agreement, Licensee should not install, copy, or otherwise use the Licensed Software. - -4. Upon Licensee's acceptance of the terms and conditions of this Agreement, Trolltech grants Licensee the right to use the Licensed Software in the manner provided below. - -5. Trolltech grants to Licensee as an individual a personal, non-exclusive, non-transferable license to make and use copies of the Licensed Software for the sole purpose of evaluating and testing the Licensed Software and/or providing feedback to Trolltech. Licensee may install copies of the Licensed Software on an unlimited number of computers provided that Licensee is the only individual using the Licensed Software. If Licensee is an entity, Trolltech grants Licensee the right to designate one, and only one, individual within Licensee's organization who shall have the sole right to use the Licensed Software in the manner provided in this Agreement. Licensee may, at any time, but not more frequently than once every six (6) months, designate another individual to replace the current designated user by notifying Trolltech, so long as there is no more than one (1) designated user at any given time - -6. Licensee may not loan, rent, lease, or license the Licensed Software or any copy of it. Licensee may not alter or remove any details of ownership, copyright, trademark or other property right connected with the Licensed Software. Licensee may not modify or distribute the Licensed Software. Licensee may not distribute any software statically or dynamically linked with the Licensed Software. - -7. This Licensed Software is time-limited. All rights granted to Licensee in this Agreement will be void three (3) months after Licensee received the Licensed Software. - -8. The Licensed Software may provide links to third party libraries or code (collectively "Third Party Libraries") to implement various functions. Third Party Libraries do not comprise part of the Licensed Software. In some cases, access to Third Party Libraries may be included along with the Licensed Software delivery as a convenience for development and testing only. Such source code and libraries as are or may be listed in the ".../src/3rdparty" source tree delivered with the Licensed Software, as may be amended from time to time, do not comprise the Licensed Software. Licensee acknowledges (1) that some Third Party Libraries may require additional licensing of copyright and patents from the owners of such, and (2) that distribution of any of the Licensed Software referencing any portion of a Third Party Library may require appropriate licensing from such third parties. - -9. Pre-Release Code, Non-Commercial Use: The Licensed Software contains Pre-release Code that is not at the level of performance and compatibility of a final, generally available, product offering. The Licensed Software may not operate correctly and may be substantially modified prior to the first commercial shipment, if any. Trolltech is not obligated to make this or any later version of the Licensed Software commercially available. The License Software is "Not for Commercial Use" and may only be used for the purposes described in Section 5. You may not use the Licensed Software in a live operating environment where it may be relied upon to perform in the same manner as a commercially released product or with data that has not been sufficiently backed up. - -10. WARRANTY DISCLAIMER: THE LICENSED SOFTWARE IS LICENSED TO LICENSEE "AS IS". TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, TROLLTECH ON BEHALF OF ITSELF AND ITS SUPPLIERS, DISCLAIMS ALL WARRANTIES AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT WITH REGARD TO THE LICENSED SOFTWARE. - -11. LIMITATION OF LIABILITY: IF, TROLLTECH'S WARRANTY DISCLAIMER NOTWITHSTANDING, TROLLTECH IS HELD LIABLE TO LICENSEE, WHETHER IN CONTRACT, TORT OR ANY OTHER LEGAL THEORY, BASED ON THE LICENSED SOFTWARE, TROLLTECH'S ENTIRE LIABILITY TO LICENSEE AND LICENSEE'S EXCLUSIVE REMEDY SHALL BE, AT TROLLTECH'S OPTION, EITHER (A) RETURN OF THE PRICE LICENSEE PAID FOR THE LICENSED SOFTWARE, OR (B) REPAIR OR REPLACEMENT OF THE LICENSED SOFTWARE, PROVIDED LICENSEE RETURNS TO TROLLTECH ALL COPIES OF THE LICENSED SOFTWARE AS ORIGINALLY DELIVERED TO LICENSEE. TROLLTECH SHALL NOT UNDER ANY CIRCUMSTANCES BE LIABLE TO LICENSEE BASED ON FAILURE OF THE LICENSED SOFTWARE IF THE FAILURE RESULTED FROM ACCIDENT, ABUSE OR MISAPPLICATION, NOR SHALL TROLLTECH UNDER ANY CIRCUMSTANCES BE LIABLE FOR SPECIAL DAMAGES, PUNITIVE OR EXEMPLARY DAMAGES, DAMAGES FOR LOSS OF PROFITS OR INTERRUPTION OF BUSINESS OR FOR LOSS OR CORRUPTION OF DATA. ANY AWARD OF DAMAGES FROM TROLLTECH TO LICENSEE SHALL NOT EXCEED THE TOTAL AMOUNT LICENSEE HAS PAID TO TROLLTECH IN CONNECTION WITH THIS AGREEMENT. - -12. Termination: Without prejudice to any other rights, Trolltech may terminate this Agreement if Licensee fails to comply with the terms and conditions of this Agreement. In such event, Licensee must destroy all copies of the Licensed Software and all of its components. - -13. Export Restrictions: Licensee agrees not to export or re-export the Licensed Software, any part thereof, or any process or service that is the direct product of the Licensed Software. Licensee may not sell, resell, or otherwise transfer for value, the Licensed Software (the foregoing collectively referred to as the "Restricted Components"), to any country, person, entity or end user subject to U.S. export restrictions. Licensee specifically agrees not to export or re-export any of the Restricted Components (i) to any country to which the U.S. has embargoed or restricted the export of goods or services, which currently include, but are not necessarily limited to Cuba, Iran, Iraq, Libya, North Korea, Sudan and Syria, or to any national of any such country, wherever located, who intends to transmit or transport the Restricted Components back to such country; (ii) to any end-user who Licensee knows or has reason to know will utilize the Restricted Components in the design, development or production of nuclear, chemical or biological weapons; or (iii) to any end-user who has been prohibited from participating in U.S. export transactions by any federal agency of the U.S. government. Licensee warrants and represents that neither the U.S. Commerce Department, Bureau of Export Administration nor any other U.S. federal agency has suspended, revoked or denied Licensee's export privileges. - -14. Government End Users: A "U.S. Government End User" shall mean any agency or entity of the government of the United States. The following shall apply if Licensee is a U.S. Government End User. The Licensed Software is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire the Licensed Software with only those rights set forth herein. The Licensed Software (including related documentation) is provided to U.S. Government End Users: (a) only as a commercial end item; and (b) only pursuant to this Agreement. - -15. Compliance with local laws: Licensee shall comply with all applicable laws and regulations relating to the Licensed Software in the United States and in other countries in which Licensee uses or modifies the Licensed Software. Without limiting the generality of the foregoing, Licensee shall not export, re-export, disclose or distribute any of the Licensed Software in violation of any applicable laws or regulations, including the export laws and regulations of the United States, and shall comply with all such laws and regulations. - -16. Entire Agreement: This Agreement constitutes the complete agreement between the parties and supersedes all prior or contemporaneous discussions, representations, and proposals, written or oral, with respect to the subject matters discussed herein. No modification of this Agreement will be effective unless contained in a writing executed by an authorized representative of each party. No term or condition contained in Licensee's purchase order will apply unless expressly accepted by Trolltech in writing. If any provision of the Agreement is found void or unenforceable, the remainder will remain valid and enforceable according to its terms. If any remedy provided is determined to have failed for its essential purpose, all limitations of liability and exclusions of damages set forth in this Agreement shall remain in effect. - -17. Governing law, legal venue: This Agreement shall be construed, interpreted and governed by the laws of Norway, the legal venue to be Oslo City Court. Trolltech reserves all rights not specifically granted in this Agreement. diff --git a/installer/resources/logo.png b/installer/resources/logo.png deleted file mode 100644 index 8a9562614b23d9508fbca6c57f2dc571b8ae5e53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1592 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4kiW$h8qca7Z?~AI14-?iy0WWg+Z8+Vb&Z8 z1_lQ95>H=O_Ul~Syi8&fQewp!7+9}+x;TbJ9DX|^I!7c`@od^&!QiV?k4c zt5@d28`a#m^UAkZ&wp)hr!#Ht&6{OqnJp6MF26ZvZoL2fpY!GWitQeq{+3oTf#)D| z+IM-6qXl2DU)g%UGL)5J!8_{-Cstovz{KDrWURC6zeAXH;O-k-ECxDN3N|bZ{b#oO z#ESDRStY=&{n)ukr=?YdjVVV*OHcLmo+*1*e7LZL>w(1I=v_rtS1+GyKR%^IC2JaI z(dan@hK-^Yzhf8e55DthU-#z;nJ{iM6EruMzz=F+_SA+Jy~^0veDN=@tb5YeQ>H}VtMtd6Ge zNcWYWS1hjyc~r27N!8o!<45O2=UG2}uU)mbY z9)D;aWvj8hWXb#7{B_m$>!l>$T+`Q>&Aj(Z-be1+7T;yM3}$J03Ox;-w)Ff>T^_?5 zsw<TmH7U#nUU72U{8_)qlI!Qt#mPe@*qJU#H}j`zcHeKR>7AIlIX% z?bPnAiR$LcXD|L$tlxj-n$WDIRq^N6R9svrUHLPl%m0B*!@56<#IxfjZ!KJ!>ozOG zgR#MdCEaLk?ajb7XC0K*m;FCDn>8r(#n0die|J_1Tl?N&aeK1(cXQ^fEvZHqc|Lw& z3;TYe*Sjfl!4DO_pQhT=K2O-%z1H}ro4%t`lm5R6KJn&jlO}u%K5YAob%wBpfzr!w zA7-&xg+DtH;+5X3J@adRVQ{e4%+;OyBRo7MTPHFGn5>YWp1phCykpx>dj^%K>Ro19 zspZluXYymxge%N9EvJZ|U6gig`)${(xml-I-AXw)Cxu06lXSD>VvEa%>ReAuat`Ir zZI%e*7va`UTU2o>@4I)d?n0LkV+FZmH=pj+R7lsH`IYfzPmtBJ@oSwnpIqIADI(kdPq}h;Riuk_TGZoD%7O>~ z&YiV4Cn+TE+a6iPrl%K@Pp^r6&ie7b)yhKE&6WMD3t5dXXr?Xi`JuA!rrwuWQPJGe zE$>3zJylc7^s8%neV5<*v7zRfi&AZDkmugY19QJ!o?GM0ba+v&{I0!jbyCukN<-r& za@+1YGRwU&t$4vkM@xe>Gp__}j|j~6^gn%W;jX1&3JH&`j|SiDU)0%_-t%|KeaYIs zTgPe|7#8fgRrKExW*QfK{q?PBhgD_4tOstrGSqGgfyj>G0l zPTQ-CN_KgB9_wqk@Z`%!#h-Uhy5zSnc=DoBiSf>bGbz)zExWZKLPGwYwcsc1owHK? zSwo*Kjo?cZeUy0AUg5P`LWbyPo%L_aH@ihYIkWc5lO30?Npanqlo+-)Y2MSXV&&f~ zPo9~(dUMa6!VAXxPyV_;N7Pr`IoQqE<+7A?vio6k7gc}%Lb;;D=N?5woQx^oc_&$n zgMou-)vK54*KQiL9q3r&p%!rGN!I-2&w1%jnNC0Ii80{yz4zR?Tx-XaTeXevcb?$? z?lEz}q?xNdxMH4$oK@OYXSq3nb8e*JC(b`d8z<--HZfskN?pdF*tu9yXIY5Cfn!3h zdY29f?EEEc*J#-GlK;=Umlq~0G$aQ8`f{abrsU5LD*qKP{O5Zif2iZg_uGD4dl?uQ O7(8A5T-G@yGywp)O88#@ diff --git a/installer/resources/watermark.png b/installer/resources/watermark.png deleted file mode 100644 index b07780d9d049bd5e70b3a67eabb18ef100b1cc02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14462 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 b{bvoBKP6P=gy|Lr1_lOCS3j3^P6 Date: Tue, 6 Jan 2009 17:03:08 +0100 Subject: [PATCH 191/230] Fixes: - Make the "Toggle Sidebar" button be a toggle button Task: - 235542 --- src/plugins/coreplugin/mainwindow.cpp | 1 + src/plugins/coreplugin/navigationwidget.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/coreplugin/mainwindow.cpp b/src/plugins/coreplugin/mainwindow.cpp index 2a9fff0f4e3..f68c5da7d06 100644 --- a/src/plugins/coreplugin/mainwindow.cpp +++ b/src/plugins/coreplugin/mainwindow.cpp @@ -625,6 +625,7 @@ void MainWindow::registerDefaultActions() // Toggle Sidebar Action m_toggleSideBarAction = new QAction(QIcon(Constants::ICON_TOGGLE_SIDEBAR), tr("Toggle Sidebar"), this); + m_toggleSideBarAction->setCheckable(true); cmd = am->registerAction(m_toggleSideBarAction, Constants::TOGGLE_SIDEBAR, m_globalContext); #ifdef Q_OS_MAC cmd->setDefaultKeySequence(QKeySequence("Ctrl+0")); diff --git a/src/plugins/coreplugin/navigationwidget.cpp b/src/plugins/coreplugin/navigationwidget.cpp index 9bbb4323d21..412559a9b0a 100644 --- a/src/plugins/coreplugin/navigationwidget.cpp +++ b/src/plugins/coreplugin/navigationwidget.cpp @@ -166,6 +166,7 @@ int NavigationWidget::storedWidth() void NavigationWidget::placeHolderChanged(NavigationWidgetPlaceHolder *holder) { m_toggleSideBarAction->setEnabled(holder); + m_toggleSideBarAction->setChecked(holder && isShown()); } void NavigationWidget::resizeEvent(QResizeEvent *re) @@ -281,8 +282,12 @@ void NavigationWidget::setShown(bool b) if (m_shown == b) return; m_shown = b; - if (NavigationWidgetPlaceHolder::m_current) + if (NavigationWidgetPlaceHolder::m_current) { NavigationWidgetPlaceHolder::m_current->setVisible(m_shown && !m_suppressed); + m_toggleSideBarAction->setChecked(m_shown); + } else { + m_toggleSideBarAction->setChecked(false); + } } bool NavigationWidget::isShown() const From 123ef3db8e8978b6801536aee1aa58daf40637bf Mon Sep 17 00:00:00 2001 From: con Date: Tue, 6 Jan 2009 17:37:45 +0100 Subject: [PATCH 192/230] Fixes: - Switch Header/Source sometimes uses wrong file Task: - 237723 Details: - Look in the same directory first, then go through project's files. --- src/plugins/cpptools/cpptoolsplugin.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index 4195fbee339..866a3d05c94 100644 --- a/src/plugins/cpptools/cpptoolsplugin.cpp +++ b/src/plugins/cpptools/cpptoolsplugin.cpp @@ -163,7 +163,8 @@ QFileInfo CppToolsPlugin::findFile(const QDir &dir, const QString &name, if (debug) qDebug() << Q_FUNC_INFO << dir << name; - if (project) { + QFileInfo fileInSameDir(dir, name); + if (project && !fileInSameDir.isFile()) { QString pattern = QString(1, QLatin1Char('/')); pattern += name; const QStringList projectFiles = project->files(ProjectExplorer::Project::AllFiles); @@ -173,7 +174,7 @@ QFileInfo CppToolsPlugin::findFile(const QDir &dir, const QString &name, return QFileInfo(*it); return QFileInfo(); } - return QFileInfo(dir, name); + return fileInSameDir; } // Figure out file type From 2e064af15da78b670cec3d270b947aece50b578a Mon Sep 17 00:00:00 2001 From: con Date: Tue, 6 Jan 2009 18:10:33 +0100 Subject: [PATCH 193/230] Fixes: - Move help collection also to qtcreator subdir. --- src/plugins/cppeditor/cpphoverhandler.cpp | 10 ++++++++-- src/plugins/help/helpplugin.cpp | 5 +++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index ba97e5a212a..6ebf51b2a2c 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -72,10 +72,16 @@ CppHoverHandler::CppHoverHandler(QObject *parent) m_modelManager = m_core->pluginManager()->getObject(); QFileInfo fi(ExtensionSystem::PluginManager::instance()->getObject()->settings()->fileName()); - m_helpEngine = new QHelpEngineCore(fi.absolutePath() + // FIXME shouldn't the help engine create the directory if it doesn't exist? + QDir directory(fi.absolutePath()+"/qtcreator"); + if (!directory.exists()) + directory.mkpath(directory.absolutePath()); + + m_helpEngine = new QHelpEngineCore(directory.absolutePath() + QLatin1String("/helpcollection.qhc"), this); //m_helpEngine->setAutoSaveFilter(false); - m_helpEngine->setupData(); + if (!m_helpEngine->setupData()) + qWarning() << "Could not initialize help engine:" << m_helpEngine->error(); m_helpEngine->setCurrentFilter(tr("Unfiltered")); m_helpEngineNeedsSetup = m_helpEngine->registeredDocumentations().count() == 0; diff --git a/src/plugins/help/helpplugin.cpp b/src/plugins/help/helpplugin.cpp index bdc98b66ee1..5ecb375240d 100644 --- a/src/plugins/help/helpplugin.cpp +++ b/src/plugins/help/helpplugin.cpp @@ -83,7 +83,8 @@ void HelpManager::registerDocumentation(const QStringList &fileNames) bool needsSetup = false; { QHelpEngineCore hc(m_helpEngine->collectionFile()); - hc.setupData(); + if (!hc.setupData()) + qWarning() << "Could not initialize help engine:" << hc.error(); foreach (const QString &fileName, fileNames) { if (!QFile::exists(fileName)) continue; @@ -132,7 +133,7 @@ bool HelpPlugin::initialize(const QStringList & /*arguments*/, QString *) // FIXME shouldn't the help engine create the directory if it doesn't exist? QFileInfo fi(m_core->settings()->fileName()); - QDir directory(fi.absolutePath()); + QDir directory(fi.absolutePath()+"/qtcreator"); if (!directory.exists()) directory.mkpath(directory.absolutePath()); m_helpEngine = new QHelpEngine(directory.absolutePath() From bbb570481b3a3e7bcae81732ec43f20228805b11 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 09:44:21 +0100 Subject: [PATCH 194/230] test the rewriter and the pretty printer. --- tests/manual/cplusplus/main.cpp | 2 +- tests/manual/cplusplus/test-pretty-printer | 3 +++ tests/manual/cplusplus/test-rewriter | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100755 tests/manual/cplusplus/test-pretty-printer create mode 100755 tests/manual/cplusplus/test-rewriter diff --git a/tests/manual/cplusplus/main.cpp b/tests/manual/cplusplus/main.cpp index b8a8e328708..c33bcbbeff7 100644 --- a/tests/manual/cplusplus/main.cpp +++ b/tests/manual/cplusplus/main.cpp @@ -231,7 +231,7 @@ int main(int argc, char *argv[]) const QByteArray appFileName = QFile::encodeName(appInfo.fileName()); printf("Usage: %s [options]\n" - " --help Display ths information\n" + " --help Display this information\n" " --test-rewriter Test the tree rewriter\n" " --test-pretty-printer Test the pretty printer\n", appFileName.constData()); diff --git a/tests/manual/cplusplus/test-pretty-printer b/tests/manual/cplusplus/test-pretty-printer new file mode 100755 index 00000000000..7403721300e --- /dev/null +++ b/tests/manual/cplusplus/test-pretty-printer @@ -0,0 +1,3 @@ +#!/bin/sh +me=$(dirname $0) +${CPP-gcc} -xc++ -E -include $me/conf.c++ $* | $me/cplusplus0 --test-pretty-printer diff --git a/tests/manual/cplusplus/test-rewriter b/tests/manual/cplusplus/test-rewriter new file mode 100755 index 00000000000..c0494257c8f --- /dev/null +++ b/tests/manual/cplusplus/test-rewriter @@ -0,0 +1,3 @@ +#!/bin/sh +me=$(dirname $0) +${CPP-gcc} -xc++ -E -include $me/conf.c++ $* | $me/cplusplus0 --test-rewriter From 8459fe70d6c80262fab59b83da3ea917722539f3 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 09:47:00 +0100 Subject: [PATCH 195/230] Added a simple test for the rewriter. --- tests/manual/cplusplus/tests/t1.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/manual/cplusplus/tests/t1.cpp diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp new file mode 100644 index 00000000000..36e1340555c --- /dev/null +++ b/tests/manual/cplusplus/tests/t1.cpp @@ -0,0 +1,12 @@ + +class foo { + int a, b; + + enum zoo { a, b }; + + typedef enum { k }; + + void foo() {} + inline void bar() {} +}; + From beee08de5a9630eb88cb088b9f07e3a74306445e Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 10:06:10 +0100 Subject: [PATCH 196/230] Test the pretty printer. --- tests/manual/cplusplus/tests/t1.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp index 36e1340555c..362146fc19b 100644 --- a/tests/manual/cplusplus/tests/t1.cpp +++ b/tests/manual/cplusplus/tests/t1.cpp @@ -1,5 +1,5 @@ -class foo { +class Class { int a, b; enum zoo { a, b }; @@ -8,5 +8,9 @@ class foo { void foo() {} inline void bar() {} + + void another_foo() { + int a = static_cast(1+2/3*4-5%6+(7&8)); + } }; From fb0d60ae66c0ae5b97536e2f4ce258e304553fee Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 10:26:27 +0100 Subject: [PATCH 197/230] Add a space before the initializer. --- shared/cplusplus/PrettyPrinter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index d6addb855b0..8a8b43bb37b 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -366,6 +366,7 @@ bool PrettyPrinter::visit(DeclaratorAST *ast) out << ' '; } if (ast->initializer) { + out << ' '; out << '='; out << ' '; accept(ast->initializer); From 0030f87e9c8e2a2cf529ffebac94ebb2fc72bf44 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 10:33:19 +0100 Subject: [PATCH 198/230] Improved the pretty printing of enum specifiers and if-else statements. --- shared/cplusplus/PrettyPrinter.cpp | 22 ++++++++++++++++------ tests/manual/cplusplus/tests/t1.cpp | 10 +++++++++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index 8a8b43bb37b..4adc69e78c3 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -453,11 +453,20 @@ bool PrettyPrinter::visit(EnumSpecifierAST *ast) out << ' '; accept(ast->name); } + out << ' '; out << '{'; - for (EnumeratorAST *it = ast->enumerators; it; it = it->next) { - accept(it); - if (it->next) - out << ", "; + if (ast->enumerators) { + indent(); + newline(); + for (EnumeratorAST *it = ast->enumerators; it; it = it->next) { + accept(it); + if (it->next) { + out << ", "; + newline(); + } + } + deindent(); + newline(); } out << '}'; return false; @@ -599,9 +608,10 @@ bool PrettyPrinter::visit(IfStatementAST *ast) out << '('; accept(ast->condition); out << ')'; - if (ast->statement->asCompoundStatement()) + if (ast->statement->asCompoundStatement()) { + out << ' '; accept(ast->statement); - else { + } else { indent(); newline(); accept(ast->statement); diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp index 362146fc19b..75c4666d55b 100644 --- a/tests/manual/cplusplus/tests/t1.cpp +++ b/tests/manual/cplusplus/tests/t1.cpp @@ -2,7 +2,9 @@ class Class { int a, b; - enum zoo { a, b }; + enum zoo { a = 1, b = a + 2 + x::y<10>::value }; + + enum {}; typedef enum { k }; @@ -12,5 +14,11 @@ class Class { void another_foo() { int a = static_cast(1+2/3*4-5%6+(7&8)); } + + void test_if() { + if (a == 10) return 1; + else if (b == 20) return 2; + else if (c == 30) { x = 1; } + } }; From 0449c67f033c59c10fe86e0ca869a8e8b77f333c Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 10:35:53 +0100 Subject: [PATCH 199/230] Fixed the pretty printing of class specifiers and base clauses. --- shared/cplusplus/PrettyPrinter.cpp | 7 ++++++- tests/manual/cplusplus/tests/t1.cpp | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index 4adc69e78c3..891a63020cd 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -145,12 +145,16 @@ bool PrettyPrinter::visit(AttributeAST *ast) bool PrettyPrinter::visit(BaseSpecifierAST *ast) { if (ast->token_virtual && ast->token_access_specifier) { - out << "virtual "; + out << "virtual"; + out << ' '; out << spell(ast->token_access_specifier); + out << ' '; } else if (ast->token_virtual) { out << "virtual"; + out << ' '; } else if (ast->token_access_specifier) { out << spell(ast->token_access_specifier); + out << ' '; } accept(ast->name); return false; @@ -234,6 +238,7 @@ bool PrettyPrinter::visit(ClassSpecifierAST *ast) out << ", "; } } + newline(); out << '{'; if (ast->member_specifiers) { indent(); diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp index 75c4666d55b..8687efb48f4 100644 --- a/tests/manual/cplusplus/tests/t1.cpp +++ b/tests/manual/cplusplus/tests/t1.cpp @@ -22,3 +22,7 @@ class Class { } }; +class Derived: public Class { +}; + +class Derived2: public Class, public virtual Derived {}; From ffbc28cbbd544e4c22f542322a9ea10a7660b8fc Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 10:38:24 +0100 Subject: [PATCH 200/230] Added a space before cv-qualifiers in a function declarator. --- shared/cplusplus/PrettyPrinter.cpp | 3 +-- tests/manual/cplusplus/tests/t1.cpp | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index 891a63020cd..d7570127e32 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -566,9 +566,8 @@ bool PrettyPrinter::visit(FunctionDeclaratorAST *ast) accept(ast->parameters); out << ')'; for (SpecifierAST *it = ast->cv_qualifier_seq; it; it = it->next) { + out << ' '; accept(it); - if (it->next) - out << ' '; } if (ast->exception_specification) { out << ' '; diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp index 8687efb48f4..186d9fbea7c 100644 --- a/tests/manual/cplusplus/tests/t1.cpp +++ b/tests/manual/cplusplus/tests/t1.cpp @@ -23,6 +23,8 @@ class Class { }; class Derived: public Class { + operator bool() const volatile throw () { return 1; } + Derived &operator++() {} }; class Derived2: public Class, public virtual Derived {}; From f63d56a13b381115c340afee17982e7fcb50cf60 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 10:42:43 +0100 Subject: [PATCH 201/230] Nicer pretty printing of while statements. --- shared/cplusplus/PrettyPrinter.cpp | 11 ++++++++++- tests/manual/cplusplus/tests/t1.cpp | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index d7570127e32..6fcd06de380 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -1229,7 +1229,16 @@ bool PrettyPrinter::visit(WhileStatementAST *ast) out << '('; accept(ast->condition); out << ')'; - accept(ast->statement); + out << ' '; + if (ast->statement && ast->statement->asCompoundStatement()) + accept(ast->statement); + else { + indent(); + newline(); + accept(ast->statement); + deindent(); + newline(); + } return false; } diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp index 186d9fbea7c..0151673c70b 100644 --- a/tests/manual/cplusplus/tests/t1.cpp +++ b/tests/manual/cplusplus/tests/t1.cpp @@ -20,6 +20,16 @@ class Class { else if (b == 20) return 2; else if (c == 30) { x = 1; } } + + void test_while() { + while (int a = 1) { + exit(); + } + + while (x==1) do_something_here(); + + while (x==2) if(a==1) c(); else if (a==2) c(); else c3(); + } }; class Derived: public Class { From 8ec03e6bcd7d7ed7ee1e22c96bcfb46b86cdc3bf Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 10:49:08 +0100 Subject: [PATCH 202/230] Pretty print char ltierals and wide char literals. --- shared/cplusplus/PrettyPrinter.cpp | 13 ++++++++++++- tests/manual/cplusplus/tests/t1.cpp | 9 +++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index 6fcd06de380..620cb0bd2a0 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -33,6 +33,7 @@ #include "PrettyPrinter.h" #include "AST.h" +#include "Token.h" #include #include #include @@ -813,7 +814,17 @@ bool PrettyPrinter::visit(NewTypeIdAST *ast) bool PrettyPrinter::visit(NumericLiteralAST *ast) { - out << spell(ast->token); + switch (tokenKind(ast->token)) { + case T_CHAR_LITERAL: + out << '\'' << spell(ast->token) << '\''; + break; + case T_WIDE_CHAR_LITERAL: + out << "L\'" << spell(ast->token) << '\''; + break; + + default: + out << spell(ast->token); + } return false; } diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp index 0151673c70b..2a64b291846 100644 --- a/tests/manual/cplusplus/tests/t1.cpp +++ b/tests/manual/cplusplus/tests/t1.cpp @@ -30,6 +30,15 @@ class Class { while (x==2) if(a==1) c(); else if (a==2) c(); else c3(); } + + void test_switch() { + switch (int k) { + case 'a': case 'b': case '\\': + return 1; + default: + return 2; + } + } }; class Derived: public Class { From f4bf0a3a6db41dd7ce6f122053a0d144c01b5bd8 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 10:59:36 +0100 Subject: [PATCH 203/230] Checkpoint. Pretty printing of switch and case statements. --- shared/cplusplus/PrettyPrinter.cpp | 19 ++++++++++++++++++- tests/manual/cplusplus/tests/t1.cpp | 5 +++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index 620cb0bd2a0..2acb98b14e1 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -198,7 +198,24 @@ bool PrettyPrinter::visit(CaseStatementAST *ast) out << "case "; accept(ast->expression); out << ':'; - accept(ast->statement); + if (! ast->statement) { + newline(); + return false; + } + + if (ast->statement->asCompoundStatement()) { + out << ' '; + accept(ast->statement); + } else if (ast->statement->asCaseStatement() || ast->statement->asLabeledStatement()) { + newline(); + accept(ast->statement); + } else { + indent(); + newline(); + accept(ast->statement); + deindent(); + newline(); + } return false; } diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp index 2a64b291846..5457def79eb 100644 --- a/tests/manual/cplusplus/tests/t1.cpp +++ b/tests/manual/cplusplus/tests/t1.cpp @@ -35,6 +35,11 @@ class Class { switch (int k) { case 'a': case 'b': case '\\': return 1; + case 1|2: { return 3; } break; + case x: break; + case y: + foo(); + break; default: return 2; } From 7fcf6cb25535c3f96a3dc453ea9583b0732ca08b Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 11:03:37 +0100 Subject: [PATCH 204/230] Pretty printing of wide string literals. --- shared/cplusplus/PrettyPrinter.cpp | 11 +++++++---- tests/manual/cplusplus/tests/t1.cpp | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/shared/cplusplus/PrettyPrinter.cpp b/shared/cplusplus/PrettyPrinter.cpp index 2acb98b14e1..72338576b6b 100644 --- a/shared/cplusplus/PrettyPrinter.cpp +++ b/shared/cplusplus/PrettyPrinter.cpp @@ -1006,10 +1006,13 @@ bool PrettyPrinter::visit(SizeofExpressionAST *ast) bool PrettyPrinter::visit(StringLiteralAST *ast) { - out << '"' << spell(ast->token) << '"'; - if (ast->next) { - out << ' '; - accept(ast->next); + for (StringLiteralAST *it = ast; it; it = it->next) { + if (tokenKind(ast->token) == T_STRING_LITERAL) + out << '"' << spell(ast->token) << '"'; + else + out << "L\"" << spell(ast->token) << '"'; + if (it->next) + out << ' '; } return false; } diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp index 5457def79eb..ce6bdcb120d 100644 --- a/tests/manual/cplusplus/tests/t1.cpp +++ b/tests/manual/cplusplus/tests/t1.cpp @@ -43,6 +43,8 @@ class Class { default: return 2; } + s = L"ci\"aa\"ao" L"blah!"; + s2 = "ciao \"ciao\" ciao"; } }; From 8c21fa63ff43103b0d384cd6e3736000a2736aea Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 7 Jan 2009 11:06:31 +0100 Subject: [PATCH 205/230] oops! --- tests/manual/cplusplus/tests/t1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/manual/cplusplus/tests/t1.cpp b/tests/manual/cplusplus/tests/t1.cpp index ce6bdcb120d..c489dd3b072 100644 --- a/tests/manual/cplusplus/tests/t1.cpp +++ b/tests/manual/cplusplus/tests/t1.cpp @@ -32,7 +32,7 @@ class Class { } void test_switch() { - switch (int k) { + switch (int k = 1) { case 'a': case 'b': case '\\': return 1; case 1|2: { return 3; } break; From 79942f06b8012df74a6251e3d6a031c6b602c3c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 7 Jan 2009 12:03:13 +0100 Subject: [PATCH 206/230] Removed qtcreator.qch from version control This large binary file really shouldn't be tracked by git. It is generated during build. --- doc/qtcreator.qch | Bin 3055616 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 doc/qtcreator.qch diff --git a/doc/qtcreator.qch b/doc/qtcreator.qch deleted file mode 100644 index 8733e749a0823e5c71ef692a926effabbfeb8106..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3055616 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

k4o`2>%vt3hjc~$6j(`}NkL?4BGv<}m_ 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

tmvpoPn0Hf=sQ#tk>JkPM6=> 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 z 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 z%0A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 +(8N`{}}9%{!gc3H2TvxFU~HQt(Au>a<~4Fxy; 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

fZCfpQ#He%; z_nyT3g-cuZe(RP>DbhV(zT7C|jN7FN6;Vso9)EDY+w_KcmX_a~^*nPOr&$WDe&3sL zH_e&*fB2;R`#(K;Q^U^qaQmsws?f`GzPuG}IL7RIE8zduj}xqmqJK2XpPVmw{ob*Y zcJKbq^eTSr8tFL0eQIXX6Fa_>^NQe>eG^qSF_?&Gya&I)|P2_#1Qk* z#a{f#+Y$>C6WbGKK2P_0aqoD`qGU(EK)qej=c=2H*w;a8~e(3%wW_zc9nI}o`Arx&l|Uf%{~$*yi4b3zPH!2 zpf&n;9JkENcsJw4j4M+0Ta$$ipYzWt{&-T`chP0vc`H}8v)pfAX7*gkub@-c_QuY$ zQ~9j_<6RMZl3iTx+QTQSC8|}EkF`w-;+{~IGp$%g;@#{c$D4LIUa5|lcwxPHz{<@` z^J83PXS41~`ue0usB6wr>p%a)gg$#{?D@#S-MdYxF=CSJLe?cyVuXKaACvoa^5@U< z9GqA9rwdHI{_c2nw~_7|ulO^ogOW89eZ5Z3SoRs}R-F#XUz+gk$=2$0X+Pf6N1omeh-o>^n_F`K@4ed&GsE66r>f>eKAf!a zFReT`r)puPMdkqHlnu9w!=k=GB-Fl++SGssZru~}4 z%MWi`%`fVG<1p>Oez8|7g;}a0TjuhFC^>1~{>?gR{r#U(^3#;}#h+PgueLPlVAqEe z^NyQamg-#pV309A-8Ji+Z*Q&JXPJGXIWK?w+ES>N`HNpP!gQtHMX(eCydF$-5dyRf#A73x&_{XzFnMetXvs?qT3A|g5Q_NRqyVT zn!o>*f?%@v)kEe|RXbNsy|9_HuJi75rmC&>ul9WuiC<-R{e8gq`FbDD|Fm3c;*;pL z`?Bc~G5K`|f2cRj-SRM$Gh}CEo^i#o6LnkrqaKIutTTzPXl{D0TY2(^Ro>KH&v<{y zztCc06Uy@3VYB{Rl*D?kryc)wt}U2XJ0odpiN%>?)0NBLUFlxq{&ex-ccBvUmySvp zJFjR?^RqZBn0euX<<0fy@J}Ftns;g(y(s!~OC+|{cYUqhJwbgy|;Nn77A8pOQZ>PrFII25ebUydf zw>u{PX}7k|(K(D;);P2GMDBlo{+>&wn{_@rD zgC|G1xlX>jq`8n$rFEd^C!8(8CkIl1E_HyrGotL6(!0h`Z;;5$6iW_dK zp0}GL6!qWg-fQ1Aac;bf{Slq=n-?bUZ<-bTW&XSN0QK3wC*S^USv*f?O=|khwWhg6 zwOjxEwaB|UyJS79a#H4ou-^DHXA|=8?BB9!|DA~5RgP=jW#3%Mj;y{=f9~d{AJ=v& z=Y>{ZZBAHvU2cP{iNs;n52=46K84R-!BMb#_ea*vJ5E#z|1sVrvGWq=rQdrw)t1FG zi==;+t>5RW8n3?N zFfVy#oJ_6Tsi}Yc3m9~D*Iqq&ZcbwF*VoM~cRv+zE(-Tw@c&P8z^3))Z>KM}SILc; zzj>O1Z(@Sn0mY}gKXY;&oA&#?*&n`#{Kj5ew?9}L)GEB!MoQ+P+*Y@}y82UZ8}QDY zZu%v{VUbJ&dt=|9HFXENt!4N9oAmv~dJq4{#Yt9IXT5LV?$Q-}c9-R_lFj^*{L z&D_wM5aFfeS+*o((W$GeLIh-Qr+eJI-x&LG<0=W(;?1Uvg@uw1#4s6uUpNR873JBv*cKbmx#7_2#YzASypWLI%%V@#;>%-#MxN4EYkdoaIa@xPQl zo-@-O;!mD2`M;U%qRYZLY?||)HYBRwidJ}aXxV$;`Qo=+vkuhnyHTGI|HRRD>-8v> z*IG=*%@?~C@V?5m3t3>Cr!(b&>Z5%+n;p%HK1rFxs&6{b*(LGukjtUBjXffHv3psS zmi*rM?PU$K%-g+J-d<68!d!KLFRky&o|3ZQ$bRwF9Q^+tZ#h>VVI#2T($wRhL&a`4 zMsJ#yt$gD|1w(@HN_(sLx4r9U-4YLeeL$-51K;`8zuY^NH%V`w$69fTt!!d^r^O-p zlzpY=&YS&rS~#iT=e$bG|94#@Z!ey;bcaOHlr#Uzt+0>Tvbr2}^xGpIo(b`mI2vPa@A=I6aD* zaY$~|);p4>8XYY@($;v0Q=vbw! z@~%x6mNMCty!rp~Tho8IXAx3o2;hK%8xM>c6st}%k9hT-)A1lb2nEm%so42@ecL8cPrf9|9jZf;>E(UCL?Np zs`_Jln>PpemsFQbY5r6$J1vUm#kHulF7je`Vm|D>!1zw<)|&HH3NeZil27GwdaJt? zPIrGUvwY+x^`W(jVY`P`)1`CARl1X|?^uv%Sg0UUZ*}Rd_H~Zn)nr|pWhxl<$Utsrw?(dyn9ZG$Ex4dJoZ-N|Nm8s z4VULy>mQuFL!)xnn$AxyXEGe_6-?}u{5k2cFzbvO!C$+LPb|p3ae#4&*}VhTEjaQ% zYI@ZLD-|*M{E*A}Rgm5=So}4XT7TDS;i3Y zE31C(7uURZ<+Wmcf7*U1`|tbi^O$YNw_{IcPkeO${jIF+H5pgr>sACNNIvmcI&VR# zSk=qeKegKCr)<{iZnIv#P3o@q9L1Gt;U8*wwb$9L`0CASZ2ao=d+U!j)&Y+g&dDhK z$UCum=c5UiqrcXvTgsi@EpO)H!lZm4u&d^ueY2eW{RSPEJ)w))U%3n2cyxUGT>jg+ zY??7*v*iuEE452+xE_dER8ytGbX7*$`C0v*N$d7zS#ooiX_lHWR@Tj2KehVw)OiNC zEbh;U(O_L=82CJTzr&mpU)JU>UHWu}tNga*RvCx$qIPU6*7&+}-I-;gQ*Zr^esk!X zoaUmH7aQspXG>SUXa3&!QN`y<&zC&!f_obsd+*tGR7vDb-2H*Ee+!?Yaia0!OKTM8 zb8W6wzv{c;0*k%;`j8#p66alfHJf|u;o1+G2MdIsullF)T8# z{L%e)ldHB~GjVmZp4G^CPy6)!)%N#xuDEc{jLo3(-0wSH+5HdSofNsVG4{Ui?LBK1 zvnQRNDSnq_&eQ&H;=dPg&*PoH_f27dA9wOXbNm==BtlgWYd!5BR5B+ZU3TnWYZz-7`c^m#kqw0D!<8g7c2d*`zDIdh8eFF+~NhT(l@FkYVU+Fk&)c*3l0nw%wLd z6bin-GP3D>q^P8=j?u(FfzRh!W!`6>=x|RpeQNcSdu=8=$#uzJ3_(|^6p z9qSd`zy1`j=l(lk&X>JQ!zL-8-+WbL-PFJ*8F7cMcH3*e*#EQb689Mull&YW^NUJ1 z=36IEs9SvH=<}Zq-!D~EJX#(WsV{WPS4vc0C)IQ6(MP2c*V9|xd9O8kanP$uL{%*N zotNpyf7`_rZcZ=OJNo{P1mi<%#mjsdCCsv)R=qvPwrkgwKtIvXi&w|EAGuk-OG$;b zQJrJO(<{IKF4tY8_A2i9{}tgk%Pz9XUhm?1R6K9iuiEU=5a}R;swjt(_qgxaS(bd_ z`>(_j?eV`-|7Ak!xwYZ?DF>yZKPGqw&9*wRsP{j+=mY1Fw%g0XG zv2)h`>dBp%yW$V?tYqx9ygQFgBlgt8es$f}hg{s*l|OWKa$ml45>9=mvdCcfi<9!) z;SU>gwHEw5b@c1(S%y_@OaFbg>Qg!4x>;8~$?!i{$9cW=S0tY zub1!a+rR(EYge^hil^Th)$J%YzIk!&zuoIEsZ>YT?&V-#$=EHMA6mlwC#IYAhnbi{ z+4Sf}!}{6PImbS--&uL*Zu+}(dffTPmhc`fDt^uT+cn?QY4^qEJEuP{>nt+XmwNHj z{#=Nqvwei}=9U*ZdSUl&-zkp$+!j8y0cQm$S6xsKd z8h<&i>6gD|v(lEgt8y5+S{))H8v)s^~?B zNMBb*k#%~J*Wc{sOtWh*KYRbn3%mAc0^8Y|uH2)kpRBSiRjj}LzEM4U{_FA_>!&he zMc2)lyZG;KI=b+5=&KLAbY65AEL{AEFURK9x$H?l_C)MwkvT5iwVJ(s%?_92MU0w) zNWjgg>&fa&p{BiIuifLtg9tS3ddU_3SMZ%f$?PCLQMM`!viwyKC+OS!t+PYx$}V%vnRn9X z>KW5>nG6g}_CbDglfn)p*ZvLovFOISRf!&fb9Xi0oz?DmXsdBz*vDH2PgbpGHDzX7 zx@MDbSCozRir(icV!^pZ$Cf+JwpISS|C4~!jql4VcV6rI+bpGNBp$K8S=l2c=J{s9 zMLQba|1pnxuO<29w$P5*-3$}{O+5cA=HJy2g)Yf1#V37d+P;0eclOErnV;CiuJG05 z`nxOlEEJ5ZyH_BkwLj%P+v;MsrCbat)3g4$#(wSy-nTOG%{SBPK*PgfpA=s+^Xas1 z{@WhEb!J1VbnFl1>ABNG&t`5CNSbo^eXQ7vmAYQP9{m>IvPHPKYDS9nO0Fw!nsqh^ z*<5%ocr4m~;iEapOwEG3|2iK&m%^CyWX{3mf#>gWT>mfiZoa}}&i#8+Dx!*hEow>; zysbVpKg>N`$K=wZ$?NV3ZuK#7eljg~?Yjiyt~K?VH<$3uUYE)C=6uZY^kZgWFpJX=-&bWf91Y8so9D#w zYHdGw?$hS~Ugnyn4bd?ctrHIQAHOFgeW$rGzI?;m@Z0}d&YG@!EZuQMa*6xY9}6F9 zKI~X<>ATX?y`N$g|J@D=Fl{p0%&UI9;IiRkEwcw(dm?{q@mD)~olkh(x2Nm>{Q7Y- ze5P+}gX-tcGfR^55M+yza(1&4~-HB)v*m@VbfdvuWP; zi8=g2rZZZ9?NTz)xE;j0$s^_wk1u1~|a%X=Q{2SJ$81*RWL0Yf$Nog_nWW8yM z%QW8l{r#9*BJVZv*W9SDFYgHjPvG=f>#wi7D{$@W?sB7&@;%AlSFdLEI#b`F8<%ri z<$cP_BcZdNPI=m}RHb{#PUg7GLJQv4tbzlz z#fk_|!_^X71bn3pBL7_ByBxf5vz*@T(wwa;I0ctJHt+oz=0A0}mbG3*?RwW4tA7Y= zt1t{b^)0h8Uqx?EU--HIT1);r%j*RmO^ea!-@hw^r|Rz6% zJB83g0UCvd+B@?9&T9Y7VKjTI)r2RSpZ8DJ(9Kc1cJ11~4Ih>F9#|y&#^C4Qe-1Xm zRWtRLu2{o-Wy7d8Hm{yXaTO*!3{y!mz{s98Dgv9ogf<^Idx{)JyZ`X;Vw1Iy%EvyNGP zVdsCjuBs4ZUl%4j&0^o3I>)~n8KL1*YtjuiKUyZHr||8^i>sb@W#vAXPCaW7!Mb7U z{z((;v^eV?7JqtFz4=n7U;kECiPq6qp2f4g6w~+@^o3jZdy7iUpWsmYV0%wZmhS|< z&?g!5KD{u0`FGm~rKu%;88QpzPTu%%4tuc{E%?-%|9?|Fspq zrT12`maaZ^<->%xdIFr{t4sN1Wt*nGIyLurti_SKwmU)`Yo9%ei}-&#cj2^_r-4D` zbxyx`{E(C0eY(Q^Xi|lKtI7MD$^r3<4qy5#lkaA>@au1;0~<<07o1()C*JzK!r7r@ z=d!c)CzhEVw>tIRD0}0*jE?Vl)vvDhJ&L;Ec;I7wx*%J;R~!QaljHhx4;1IHCH|cs z@$Y|g$hZGZx4!+qt|(w2wRIg2_p0Z2a^7s3CC75MQGLxn-k+iKyDrLg_fNgKY>St5 z+K(SheEaV`ntM=W5!Y|Ep#ARhOFzyGi7vaJW&MBh(+xLtOy;W0V7^x8^MzMz#U-!n zE-$y4B%RpApsCRJ=cv^uetw6$OiTZ><*qs67FYFu)l2g`ks1eXJ8gaJGP}nAP1(*H zaYs)#F|f%V&QMH!sz3Y9PQ&Q_oVRbe<*IVe*C`#J^wHRP(ZiP(4DoywYWc}I4znwM zPL!B>_WQXH@+vos#cwcf6#m9~$can;!%UqU4Mv?u>L(Vzx|?FJa`jb6=Ua*GGFt5K zEQ4~Melg4b7PxZq&-X9leda&Azu3%4&oxBf-g5oH&WGiPcOGwaTK{%U>te}gJ;MK= zrT+V!(sjzZ)i!U|+Hw~;C5G(v@%!hk-56*yBm3hcE4>x&N)zAgI@qDL`Q|qTd;TQj z74{3b+8;lAT%DVeQev>Nm%V&a5P|&2V z7P(A?3kSoZJALYVHW;s(%ClUNGgHw-mh-K!+@6rFn-70`)GuIYfB$dF4A6#X?UINo ziaDw$?x)>1yvOXvaQs20&p-92VUxLDPXE<)Cu5t0#&@mryRTSn<(zO~OZD@FiKYK* z-rik*??&+Do-9SS##K-GU6Z{%zfM|x>deCXF**|GEn*j}d0!!JAHC^(`lYVd(TlXQ z!W7q-b>08e*Iy9B`uu0#6jr+`?_*iMEKAky7=6+AOn%^$+u1mATQ;BH#^W1wn`JM5 zxV|y-a3@m>ck}0nUn?FQTU;EX@sVeJWK92xFYNy^cc0#*7{E}c{h~XjSA6p$!G|1| zZ`TyOt%!(ZkyxQEc1@|PhpE;eXKR%FKZ8k&)bn0*8SH$%+}CyA+hWoCKUZB*XCHQsI zI_>Y4;yda#=!%~8+*$Q$nP!`eUGcVHt&ZOZug%*ZHAnUPO*!xVZV6Hw_WevVb!1&W zC#U4u-on*uokiMmH=9-#<)_*er6)9#zr)HBdUgt$JbJQX()qCaQi85(FTMsF_Qjd)zEIX5LcHirDTvJNEVYZUzP>r`6|sG8A$x?)4^JR=T2|7j^bfsR8qS z9vdf)?I$i4FL}QAK;xV1@AmKBx@#H3{k1ZS-530=+1;)%`Dwx7V-5Q^JwMKTQ(>C@ zJ5IfiGadUV%5eL{_vtSjSKHr@o4>c_<`T=ArEM>{R==9UQTR7DJ?4OH z-4rV^|3{N-f7j2be!oC%x88+t7sn+lS2RpnpwMB$_)=BNYx<3sEF7*a7pxTp1p_jb zG`vDHwN$_GEo67;*wP~B#4X_E#6RK5f!}ra_ddT@f9}jo|V3=TipJw z->N1(Op5=Xu6MpfeE!#U-qGiO#$V|xzq+|o?a_Plh_b(R9iL)1ZsOXKJnM*L|NQkX zayPc#YqUSib$xZPzU1L%8Qzbq*S0Y#b@i>@f9|uk<>&lP@>EC zX#SzS2h?q6TP^Y0Al=q-dC}@wzm7|$D5e@7=cXDUk0u7O!ZPDJ}7DygCrewF| zj^w;Y-zIJPlfmg_b!tPz?~S`QOQk)z@@8XHVpY{U)vo*Xs^T{m+{?bZ{n4-GQH#Hw zJ8pOSOTUMMQIxFYN+wxb`%^-`)uB9Me`M{G^A`S7O}%k{W6jZur-h5>-n}~IzWVei z6=B<0qr*Q;oMzhGRt?P-{=VeWieFK?T2U9-h3K-R>=H-MBN8YdX{A}NFIVwubj7tvoY20`E_*#w4XSgNJ zh1^cxn_YRUS(<0d`juaE7Ai}Lw_W)*>*(h{1?oQe=kq_$sh*G}6B{+szK`{d+rI_kG4oD&k$G}(Ca*i7xr$!D{w+YFcd z*ncqa*}Hj<(l!6A`1t2Tb5fpU(czOQ)J=Z!($&J>D>!?{x+x)AtC{Yd z`2OwfA=`p~V(T~Ao~n{CWJq4e^5*N2wZ5SYE55w<2@GHCbYk(x&(W!WH2QsZ99h6o z$$aL(F zX+(x+JvP_@SbqP*YwWcjj6WN_wIA) zlhKTSFfT##kNdoq3-gvq87=L(U2A`P>c&Ii6Rzd!P1Ma1_mYa(EBo!*&a;>JKitZ0 zsQq^Cn3U?`dvU*R{Z%;rzDXrU|MClu!otG`W^QlmGu?SnFfC-dO2wyF_XU<@>mB$r zaZ9Y$vMZNPhE1C-asR;Qo9?Mw>-v5~1})~1VTwQPC#6yS{@u62wdXUgbzGXh{l8=F zyHyTJ53Y5!MEIQ7edX|+bFY)h%81p+inRXj_PBWV&g-BzasCIt%vL%mdw$xrFZ-W1 zG=0kF-RE|EgWl@wj}r^b!+(|hGsE)8JLgY& zuQ-#u$ND5M-}J5PYLm~X_)K@ov)jDXVb!`{nJgxsj>nWy!F{LuKCAOtdkx~-+SsAQ{$X%wmZl*=JtNg4vAx)fkBH^(v~e&Rp^^1BOI<+ zS`*5%d-+lmRm++u+KoK#dW7aodsid#ip4+8ZI9-m=P%27-k+H;DfQ&1nDFU)47YBz zkG>s0?XSa%pjQ2P8`TcBox0iGkn38WaP1?r^$s0DCy!sdxm-FF-d}BIDxDBh(l$%- zt3ny0*=EB%3zs!29Eg#)BRgf)=^bZG-Haz}bj=KXGhy*t!Mxnk_GZ_ncGoqU`}P&9 zrv3Trt=?A`*}}lUel8RJ%>IJo@xhJhRUelBE!$SVMZ{ZXo6eGl z@19?|ynp4B$xHryQEv|6x^MnUIW6<`-IGP)31{xl_tA^-oyh$2+1U@<&-LouGyJ!y zE-5zYkL=`%d6SN=4muX8s^YfxCOf;}``p*lGxwWCR?XXJreFW`Smq)Hzn?KXXFmKl z{X)L}oq1}_IWNq!_O$#wCZSWWlbx^K-RI6X_1?SJ(|-oJDaCU=nfbO!Kq+L4()w?Y zf1T|(TzE)xl|`NH8T*xI7k@}Uo$x%r!{hz`xi|MLPt$hcx4f_=xA@N7JDE>J&lGp1 z8ziq6GnMuJ8l$b~mwH5e>oV602ae1)Ph^`b!j_A9tpCyYQ19_+o$VKYacujv^7t1o z>GHe~wK=}uulRgDtm9=qq0Y>*_RFi88&B;$6#eM5#n+F9^NrsvWWUZ=78e@0E&9_x zqf5F^>jfqr-4r)#F>mzu|5q-bkIa=`6~Gysb*yQtOsLswnOiw~84gcs%Ti7Jb!KjJ zuTPo&8CI6_ORnDC^@H^k`(FE_CudikpVw~(g($^NH>pLTXLibucOBROf#@7nJVeRuAh z^F6nG=G;g>p>@V{!kwf$4SaGv)UKwjE}8wJdFPaksl7KF-m>IpC+`!vdVNRsl{4#$ za?Zb6D?V95l>d(X?|t6c3-0_CYTDwSNzt?`!6 zBDbISmOkFCo3zd9o~`OT<5un6yJvBoW1ZH^s?DCo!7ZnKv}xl5q58e^8)O7sMP~+c z&+o1ax0iUPxbwnBPVuJrD|6O9(p>$-YeL5AwKAL~rKWM4lHbcc&EQ_KHscn{N}m1l zb@`eTUPb2pG%HZbRcqN{BFuMGtMtf6t@QFc9d~vKbL8eeI~=y;{r$E`sSA(F>^+XE zy0sNn{r~%C+5*G5cV^C8C$GHC=M-e3-7e6FK5x&ZqZV6 zLweIIv6S2IPTT(wNqTu_CtHnl?P*?{18dJRx-E_3JX{`be`5OCiPmd2GhdSu?b;ic zJuPm2jiK4jB^!%h<#vaL)y(?uZduV0To_mWkyoew%b8opH}-st`}zH;WTUOB>va~J zur+fEG7}^E9zK|KO8e^PG>fMeACBc{G`jyj<>0w z`?mDF=+n_-e9T(Tw4vop3y*cjHeI>oC7V~@v^uci#4pWjcX^L)ZkE038nxT?{Hedo zL@!63-C}<>L%w6imbY6i(p7jkTO`gIY<#u-)x=ZVL~_%Aiatx4A$o8_`Bw9UXJ0b+ zDVgT920fG7_UVGl-wUCi@4oJ4cQh&Lie0hV(qP8g^~XB7t)I-Oyc4wG*Rq|~XVj7{ zzZf0+)IGOFc+2UQL{Hd<=_tqwhskSG(+Vx#_ zPTBl@k4w?{!+OON)_*Vb@1L2YZu{*({K?Z_b={PG?7nh*sr#h-WzQwPuX8UNykK}) z_0H(n&2q_n9aFxjvbrgjCGOMKyk>LzCT^9kcg5BF%)bji<&@X{?A#Q1RkEVpxwbp? z$nRaZw7)ht86M9oURCzuOWFC}IR53FYrp;ccSnh-C2E?XCL51f>(bk$+QJp(QKeU% z&Ej23)-L>0rGI|QEZh7`U0n~?8T4GfR`_AwqU(ZcCpKpPlQ%kaAnf>&`0F}vgG2O7 zzo?yXcymwh{)IWRU-uX<{o)=LyUtBAePKp-^_}^jzWg~jTdV%k{HqfK|LvbX>#fJz z#i!IRYh@ z^Sx838Ozt2MN)5$wPqflBb(+N{YCNeqA#)H*{|=OZl0SisS@BXl6s1Pfyu3kGitZS zyXQM+PCeMpag;-oP4kUHx4wVXpUjy09io~VldURm3G6Ibd1|Be4Vw*LJ7-;PKelbZ z(!(|D-uoXkP367jcI1CF_Xc}yDdFAn^IP9ubG&NP<^6qceY0uTb)VIOBd8W%FhD!@e1Lpm)cYE^bm(G$hX+A$`KHd6`9++vJRxOmU{5q|!U8uPJ!c-~ojPtktJXPDjv9+f0$cdnT zNfAlw8Z9$k>aB3-UcYtQ;TVMi>wLk2MRs$yoVME&3Sk!&_A6%;-EB%Yty7QJ$^gS2<1!u5Yy@k#IA zE0~;dGjDruWTm^{!jAZ(2PO5z?#_yO;C^Deo%u^wWv&xFZ~RL_0v5g6?6u&=?`w|> ztE);Uf8T8PzfmhwW%APHNhfU>ihH*m-Q06VqR6Uqvl+*-?9ZXMgLW#MtNT9t_v2qO z&(Ek{e^Tg};XUt6UTmZ5QQaMrIOEj%*EQ@+-pCq}x?|anR6jr=J#YpBJ5*a@2i6xv81_u`f*gJkG}sUSt*f)4TkS?Dwo5#$(cC=k_%72IX=c-K(ap}J=k?o)8En>O-`=wKhC$>M2kad=xBQfRwo9~Zh zH@w&vb1T(gu2fuwvYY>u7#)6lk+qDW0t(YhHkVhtO~}h^QF(r)h5793PZ9U4Di-QD zw}0*yIdn{@`qh^&8#e#>vAM-Fkx`$obh>rT(+fsVJHH=SaeSxzn*XYXZo|6Y8g7So z{Fk`0J5+Ng_d(O3pMU0DJ=DDa`-~&|=dFML@+1GuSC#e;PfrpnoBRIwow$Xz^4D7w z?}vP7NSXOnOSil0gN3cx#pk_i-O6siy+uYO%zx zG|7O30|8gOE5jySkxS4O7P>9|f11k2pLtJNL|$(D-^k%NDdP6$RU%9q-<*4ULVztV z^R27n_Q_el%%^`l!Sp=)7@s2h`~HJ39=aOWK4*#D@x(LXg}T98#-ysFja3s06F&TH z@Z!27a%=UWtxNOnmml44ZhBROJ*(x$gl-{ikF_t7=5tPW(A-tzxZ>8X7TG7)o;|;i zSpVtmzPYM9_tu^K%Ip2T<=wQ3oE4|r-)cPnu=V~Lbv4Vq zoer}~It(L>n;$RKS~Q{czM)hAr>*OhUkA0fwCn$s`cksJGGgTy>#eIh+t;PK`df=} zuc>?xcs5q)!mpcmgIr!!C}(`X`=NJoUMw&BR(*|Y_wHVETRQVz@WG4a_v|_jmftAS z@b5czbhCM|=;FzKRSI693t`U+ZqAUSSm7c*4#wY1YD&L$c-PYs(FSBKVIt1sY#x zKC#T$vi@tD=DD}WPxXdvNa{T!DgU@$onvXcZIn~8tWJjQ%qRu13A?_2Tk`4Fwkcs# zHmDdH-D7<3c}6Su&c{DY>Q7^CPWZcEF?;njj@!HamWF*V08R$*ae&OU-=z@^?q2vFXZRUz1O(`IIJ1+hxs|%6%)a zCz`J>^-qr}$epufU(sCiN%yoxr1Usq!b3jHIaQqTddllrj@u%g{3l(uQ=jbbwe3<+ z-jd>V${${t?NT?2h-W?&^t4=dU&evJ(_TyZg--bAH;Q>)dE#&C@=<=$>Nks~-pc)! zcbzj;H9s$V!T#fI#~L4eX>H!wEnc%P*EgSc%7X)|R=kbZ44Qaa{8jtBRe!qvEjF%~ z4K~?jq26YkeYsQ0X7`Nj!xBE{zFlb4kNNL5sbI@xMj4kA2RRl8e|(p;b=%SNXQ%D^ z&g@{-#CK|EMH|bii~AFdCmh&2&sp;{ALkb?kE1DGIVQhqbQk0+q_14y^YTnW(>kfO zU*rrp&aT1mL(90r{BD-5Hm5UI{n%r8zQxWxKaviQ+t=xBqL| z!e_pX-zV{ZTf2Aa?!2{u&NoW_DNek7%I*2ub^ZP4m-Q_^_UifHxYyhHchvHgYwVDtgJe4>ndmIA^&A-&+BC` zy|C4u=bz0}_f!+xF4@dIe)+q-Ud>`)VDcylQ+brL_Q$~p`JX4ZH<&Xox;SI^&5JeD zX8uuF?C>a0(NgeIz|K!AT9=)$4_m%nYLnfWeO_qp@M-mRUtLErr66%~yQUk>#D zYZWqBvpD%n<=IIFn{Ny7Y~6GCh0LZ1`+&}n>>ClG`6{^h={zQ#`buZW+|)a^@g&G!>qv_$&3>a~;m^@7UpcbpSlzh&1yx#Y%=ZR_rw zGULiPUOIUPf6qgWWUgo5gOy_MFFU$s&i4O@lJ7H5JHGB~;n_RqeE-;|%y{j~Ruk?u zY1@HhPRFTty3T~Tz53WcZP62MALVOqu6KVmtJ*}BEK6OZo$UTvN!PV}S5vM8zx45= zm(%t%uMWKJEx-E866cpJCpN_HEq!|1=ib4&tTS)1MEW&sGh6V(xVrE{&&m~6+lsq) zwk|yPBi1yUD`Cc0uDAfTDR*CoemBrdcaGN8%sU}sbWFb6|10O2E4oWHPgqt&EfrZA zyHfqeg*DpkW|N$~N}QT)Q?;`MMC07$r^@IZ+IxlX-`^4iAqKW>j~&v4Oy8WBZcWu| zf3^CP>ObGlyHDvFrKNr?_6Xl>uzrr_^i@ZAvuYAjCuZ_J`TH^f0Nh$ymUXX!Z*0!!By8MceLlIm>n;;Jt=wDyg2{$W|arD zLzwd=_5Zz*p1OSBvKQNzSe-d*Xq6SSbE);YscIj?D#KmuRx}CZ&i~=JNPE@UIaL$3 z#<`w5b$yq}|9S2S+ANDMYM%U1e8c6Q*s^Wg>`V@GW|xS!FV<_n?rLx-c*dXZg4LyL zGwbi=9Mju-Sn4Gx&3Fa#c*s-(GP>hP|n z4d0(^bO;aB3;i3LQF}Bp%yDD0v;V)gnXhGH4lv(3cH~rBf{W4lXWl7Yk5}$x+$?pj zU@h~NYbp8)U+zerH4yz9D`^uJe&KWdO&+anUX{O6e`MFRFKr0F{NGg6N%ZOe3r|JY z-e<|vIUTDvk*A*5=HJY%z4{5KPYT^KJ20v2azgl#_cyICU%4R2`OaJa@O`&J?>TE^ zas&=8uL{e^vtYdPEbz$n2ft^AE9%s7zLoARIw?Ige|F#cXMaiH^OIPYn0EJ) z?`+E^Fz=~+8I`16{9TUn(X7%x>zEC^wpJ^e=7A4h?YOS!xCKh}8~JpXvi zZm*_m|DSjFU8MVB*WRouvM9-Kof3QL&@bUj8>1!odu0=@UAw=_E1>$BdWD7dp8e&& zcFanyou#(Nj;;OEL|>(~k#!tPQz{pE6z_er!2gZQ&3V@^d{?}s_}=nW*tI&b;-o5} z!#m?tEVUWpoo5_8c=}+L{yce~1J9P#d9b-8y?ZNUG4IR0RSG8yn^xwtxXXPq|H)~i zR9DF+l5%Yx*Y~ydJu@mA78ZNm_t0H@+W3?UPifkhM$_`ZLj{l8!nOEJ%p~R)&dDkA zi@-4r#c-#vWo5kOqIdOZx((j0G_4}(+q^8YEp1vq_xts1w#j|1&ti8#szBTUo=}AXSejE+_qF$4g7QwUOU((U;vaPXmv}Q!M zhqzyPQYjHqGvn@!#c%FzyLWeSPV4*liozI49mAewxAQ;Vn4WM-HPA?(wfg-Rx6(5!cFClFM=13>V2P8e0aV<>MA)cu|FEz zGd^*+2K?G-may}A8<%eSVbRR_i!bwhuwB{5EPFIACR^F{;A;P~*-eWRXGdP+yO6h6 zX7Amd-A10(?|5&nyZfqp>e}0{Yn}eR-^%%7!!d|MxP_PAMY)1`*i2} zCdIkyi&MR1e{FSdV|6~`yZQ8K@g4g6Kga(5?7lu@r|Bn6xBT^t>1SBOf@%{My^MPK ztu=5*!~4i5(=LS-XnEY0QR!uwwXF5-!-^pH{|<6T--o~0^qr^Imnm|U@2aWokAK%4 zb7nJ)dn{XEGRs*sk$KJa){AA^4^8Y0V>)fEqV)Ql-2OcGSF4L=?!Nu}{SJv<8Mhfy z1-xB17AK~ky1X&!_WtdEHIrtQ0K#V zcU{2xe^AIAsdOoyJFOvdr4LpgHMzxd`bQztg8QD4-Z%R{pI8!Wzjxga(;0`(nkCeK z@;u(3(&p+NUzs2Ze~3=x9VaS%i+waqUi^t?){#rKcV5l z3w!qI+C1v-I~r$)T&)(qR@cUB%Y0}0?#R0K2H{+p4w zKi}k7j{J$pnMO=q;+8vpEuB)fc-gEXn~pz6S8p-3-#7WxtaIg@x=Kv9%5MM7J2P?P zLDn7HCa?QyVQ&0H_IQU>kD^k9I!pBt^CxNVcCTHw;r*$b{>@kBM%@0e?Qs3)Wl|c? z0-n1(FKTLdU%Er@WQ$2(ck0#&H*BO{KCewR3v%h2{$J%WbZ> zRHB}@cY?uYutZdd>ZE;<8USMHx&hum4+*@N!1@>Sui{`{1Z- z=8D4o99pU8k4j0LxmNwaXj8&+BYUaqi(eJQ&9`3u)^Wk@1#Fso@(<3qy9{RRlxtpL1E{#j^cdFY4^q zNq^bcbG~&-R@|{u)!WYY#ux{_{TFf3smtQHms0GFj+(vRzd1()bH)yPE?FlTI&QdvUoYr}2TAesW%+-3`i<{0_X;dLiqxYT`+G zt`E=D<|jVPYmDOzGnYHN@3CM(&9<2iFD=_Yh(u-gJkmR|Fj#!)qn0DDE!y61ydxsE z;bQ$fmiZqXt&aCeD=;|7x8J%E$MSAd`S0?A@a0k)SI@{ilktfCcaEo#W!>Ky>Q~Rb zl<>UpTs3`qcH4c$8ec)aR%Nw(Z>xnmZNe(0ZYy?eOZu^)eTEv#f%(7IbWCMT{`)fX zfYUamI-M;Cb9!3rYCIxhB=&v%^G$clcjvl$mleN7*;ahLWUU}MHM722=i8@W*~W7| zB|hHB7Ij)McCr2Jp2NwjwUjy6&-tUp7d@@>%gzgrl1 z)2cSPpl{({HZiSvz`yUxonu_nqULvUlX;J#+qfqDkggS4j#+l;cU3PEGE)JyKYOciP7oRYo9OwmiKbz z`{X#Ul_^)Yov@v^dgr=5cfu}wHhb~@{${xgebrkx-BS!-^i zU4FbNOT@OC?%TXSKZ!5$S_NxvvDwn2Tkb9IiN5)K&Bg^`3~|ZtpP1cFe*Vr)VSYx| zv$&j|SH=mA*8aC=@0>f2ztoKBQkB!zle3rn(_ZlL?O%D8`4f)LeO7%?M|Ja8rp>Xc zifwEEMOmIRt}#{GP;;Zi@G-N;%(86h58wY8KVV>B^5OgL@$mrjzvA9St_@Njcz0j2 z-(tTn>)Uze6~_LR&mNs9yuxPtv^+0ulO4yDk7l*A;&y!$O4-rfDD+Ar#KCvZuP~AD z&)(S+8ebcCUOw>hQ0M8nDa{8}mL1yMG}Vmt!c50lzDc4?`|Wp5e%o_W!f{r0ywmaDk%rEBwrBu}2nOHCCPx&8nDyQCiz!Y3cUdhvAamy;8=uDi%}U8lv3ampUY z%O9opRqQx*t}2ITF58;(UCYHi)-e1$y#H=)snFR;m!@6Zx2E&|j(nb6m)fdp_N9kY zRkOU;ldznHT>VNGn?a%C(wB7dVsihljv?eWOE_2*p`fH_K*~wMHu|W!sKcZQ9&p3YV z|1Gbvdd>a?6`t>XcPL4xeQww?|M5a=;a8cb6Tb*-!o(`VE5Vv8KOb>Drr zX=hA(ZW$|^Df_CMx#~da>t~x&_|0dWVyyc<;ZnO3#{|i*3R{1P#r#+1T>DovQ&;1S zC6mxP`TEC7XRfs!zni6g>Fv++PkPcC__nQnka+lw`jVpSjH)$eVXWCAyBg-puP)o3 zXEfvU#7iO{I9NZ-Hf8z!wyE!{hRy%qrIoKkR;O6r^-bUji2FD#iZ}VgU9b3%O;7Z^ z#4f)$*_`cpm{V8q-jlSj#aiE`{$y<2vxjMqOqXe7*3uOlJ>=j15!>;+kT)Vje+EmJ z;CHKYtiEeAENUjNzm;JXUb6Vqx~Z+ZCZ3#dFMcIcz12F#vZ)`utWMs#ml#=IINk5| z`8_-8jJZTF%;My)sG4fWF}-<;WrXuKxs*%dku7pR-+qponXWhY$-3yB$I_o_tn#^- z?|Sdgsg4rYH(%z?(KUwx;@O#Tn_EPKS?f+MDnQAPK;H`1H9ecZJ zW9r24JKMQ7HcZ+1uI$;?_|%nmFF5YknRMmV@l%Rd`}+79UU6+$HnlH$QnbMJOYB=* zd7Dbt=3l=tdzE2(Rp9ew^|^jMmJ49BTeVP6^<#8@LDB20`*h|XmYcXJ z=JB6Jg{R&faa+wW&1Bi(LSFXI;_o-K8OT}GMzHEQOG%x0b?MbQ)(J;s-nM=g^XKwc zQJZcr{Na>^{D-)oVxE2C!dlZFp1yhH+UY!}Z-r{kMfudan!(eCX}_P=wnjbhG8 zHwgDDIxNQG#G`g#f7SP1%Xjg2`IU3DzxT3s@7nxL<(_E6-v2T7Ui-q67_7cCE_?s% z$BKm0-IGMtso%LMwe+RhsikZ8S2s$^7~P$oQ!+)ck9)Jjqv<8-Vvnr)_dd}0yG2<3 z`plk}Rz`ek&)0M5%QiG)^~$$4L6!SU-cEXLsF$m6q_|u4(vQ1;zb;?jG0QhqVT*3b?bDy; z_^wcBxxr@25tC|ud)j%4&30F6Z&=;uuaDwe7_H!RzIk%;s%f8>_j}qY^m(?{L_0?O zd(rSlesSt6yKPz@>aM8O&!24((O=3G@-#=WSNLc6zi4iSO1VQ@wSxjDyPY;S_-pjZ zry*&6#*C`B3T}EwPC6*5`>vV0=GOB?YFG7M75eQyT^aw*^x~SeERVnU+sxql^fp$% zB6QW8Pt^{`{zl4q)FjJd6Ldx54H9 zg`3`=a%G9St(g3Nvz$bIaNjZ6kYnAM@9w9_o}T$?vas^@_b;!?Z>`pyywcC|;q3?0 zG~I391Uxd2>$6*Bym;>V#m323e*L>$8j+}Vc}K?O!aY->v(`Kjn;RLB^ZvN&fnQ30 zV@}9#e~_JX;oy?xMz@mrldeC^%XRDw=v;2k)ov1gZ_&*d{TIbYJ@>6^dS(A)i{{Rb zg}mDNWnarxT2Ci7S{rZe3YPJFG5y*~@wIm|#G{TUypt1_;TB!tZ^0rI8Zn*mww=fy zk>i!Wmw8^i$ouPYfzk@GP`M-J znyrhCG+)Q;^(i%r2`yj4Rv;n0>qkfIjtu*gYj-~1U$Nr6Hg>GIWewX4$Ue5L@vzVbGvEFxrJ;WIk#Q%-oDNK zzQZgN`G3;Bl5AQpMJKI2C*p8Ni}CRL;vp`)I2MTwyZ2& zJ3s#ZKF-t6mc=h=^G*1!wJj|DUwYT7Gxc$PUJ}<7mOVJW`^N@Ornnm?e10}?HB*M|93Bcw5{exCXwKS|Gd<-x1IW*mhj>2 zbhUS$i`(noOjMh=Ah%Ci+^5V#&bjoBFkkggjr{J@MM@f_|D)L@m|yHI?ff|*nme?A z)ygU>9bHBCdH?g;=ILC|7BE-(E5oj4%fXF3 z|5tJTz4hdCDTm?iCAW7cPoHqD_K(|Nx5*tM+O=h8p9Zxb<~Zk?q5L~1d&lIj5sJ${ zZho2LzHsvM%kzqFW=_&`4AbGrIhzYl?M!{e{~X=BquP`sq*pl5^XG^mNuund54HcZbcN`KMa54+*I+ zJF?5~R^Le(L60eEEI%z>CQn(!Ea`TATmMYolktCk6n5ESoie6-FNJl7tE38wEMr}!D}=3Adbh!&Hire`Nn&D?vkpIpLT9* zp87m`u$e36u~7TG)meU}K{of+jU%?Uym4p0 z%9p>MrgUO);lod?k;0blVi&4;G&_AgICMSMwW=>D7MX1^Nv9#qj&<7C#RtDyPgZ>V zefO2lO@B5g{*Tnq);->(QT%V`s>en8%2fpmZ*0!UeIsGLU~%LFJ+qF3YFD(X-``xl zF7Nc8h|mkxytR$%qfcIRd0YB)&d2FC^;_Dxj2Fi{UP*cXxJ4ro zj9)DUC1#fkZ=Kk)vy}6RQ~T7%2i(u!c`mSJukOmDd*{iX{Ih4C%PrTmb&fsamiHMg z79ZaHccIuhJD=lFuhH&z*ajcI4Sy8NX6|p0ZZ=eUM?Rdly>?_xA0qT z!^~ORU1AlSa~L*CHl5pfYV#U~jm=xEbWb^b-|uYKwl^|L=5@Km54kgU#wIjWN*DSh1FmeWH~dD*wx z=;!w>?YCcsD+h)t zwmW&7Ziuv{GmM>g959X`yDLXf3 z`&#SuJH-nZUF`X&_8@-6#-p9uDpxPv7ZftE>^dGH7qRcb+4EbDD_$_}UUPV3cl{a?OxwX5r?#rd6ouZO0u`{_4--433A-+uCakv$i`;OcUTT@z*qYoFxO zb6B(JKl8TIQ$|}4R|icDz4Gy7)W7}fI3!gT*K%6!dd~j&wxfXI6{G8pGKXrZSM8_JI-9&^5NtAL|wz2?rRlfx?gCEskjm%_gB z&)*4a3x8OPty{(&dsTY#)yjj61`kp--5Ht8!~3|5>a6!4VQm$8aQ&;;y(3#qH?F(z zTW$L_GnD$y=3K^8RQO0v(2k^ z70SfCxF=V~{4@K&cc`OLv06Jy1EE9?+2r+)h` z)%}-*|GE1{ohf!bU~wm9q3PS+WqtF4g{Rf(9Pe6~CY)mLwvgw;x$TMe4vOxVBK#un zzqZ=);lD6!D_+|giefsvL+im~k zWMZ_%;n2IoFCrh+i~p?*dj8P7XHDQ-9n;r9KN77anrSvG1n?elTAaJ=5P9X zsn^*Hu`Wm^rNvc^# zg9V(jAMa2Me4yxj$=E6|araE$$sId>nE1TA^t_wDkL^$0{SW&$R0g^{&Awa^_jcNO z=lqw>WxH9@uB$Bi$+q~|@#^N(Z(jud8)vT)sp!>ox)XF<=jjaXRNi_ftFG=PN0%R5 z=>OnV(b_3hf8I+z+4K8EC{ytzpa0JkYTwwLijlB*?sl~9Koe!nHb~ISn}hpSE3O zx^-;wiB~pNIS&+6Pd(VLBT-iGtZ%!@z3;Vv>G@6N8&4Od9egb3eY?Mac~wcrs%Vzz zBUcYZu2)`ftnz32DI zRxV6?(j#*HTG&~!(njGL0lO825>Ia_$xU1mnLOFnTqSO^xkvu7MRMl_1HXn9-m2z$ zCa&)LC|{s8wc_K{OIt0(7hK6&J2S7!<5lPLRX6fp=P!J1D_#8M%o*?E!+MnyB7dToxXJrcEQ%hD{v0Ay6XR4-KwyAVgjnv0=D!TGV zdY`#6oqT@2PU*-GUav#<^w}@eI?OcMQ(v)4zWm_g{N)cPSXj#3zErY9^uoEbJ&U*f z+!z*m-$7zx_H4_GqFPZAD~#USugMI!cZPw1Dd^WW?fJqrc2~=7Kibc<_Ntz@;Mp(U z#J7>V>x=R|_T3Gf_v6_AC4B77ndd|FUb5avtz@W-4{X-(@DiOr;X~Z-dV zZQhl$6BZcE&XIQOUQwR??eWd0S{HuLVt9Py2Sf46Ry;xHFwks^4byrT$r= z!j2%ei0UcdrYmmVt;oo^a&`O?p|1^#_Bh#HWL+*Ta9Uq+^Jb+rADM)f2`>z7(%9p< z@^PEf*-Poo?ph&*S>_g>|JrT*{@9%N{`NJ84oO8{d9y`G>H1=yQ{L%D;?i21EG=`& zp7ipy-*Aj!_{-SO8!+!DzxFiVZ}axlhpd@$Y0L3%8R~@+HOKAd_43|`sk*z*@-4qNK>z;Cx9o=w#vHnOQReWG;P|YZ_zB#b zsy=-+{%O=?v1-NEy_~KGwuWckEm^dbNyqr$?$jOc>jOT|OZ3f+y}hEN$?J9(mxr)m z;KaTXAwf|=MI|LARVF3VFG5~If~*s@I66!ws_hl75_J-E@@-&PxLrVDi-Xf7{_pqB zSKlkHyMbO`ICA zWy;+(Z92Cvu9xnW_BK;}wMe0D@jNEy_p`5`+sy1_JNv9n!&YNk^Y*7~ zmh5gR+uz02o5y|aViJd~sC7OS?HRW%5 z;%6!I=jJB+)e?~+-qG$mjeYqW_N%Rt-_NLi zJ$Gxb=H1)7-yalyl_S&PZo_ly=Z_-y;LI6|eRi*0;kKuap?%f4O{seAb=v|?77A28 z+i0Hi?)A^QNqp(sPHJk&T5i`4TE=d=BA3O-bn(fae0%bQwuTSu@9?DRHg_|`aIEY5aC`|j{_LPcx3 zTcx?Sm5G{MOrO6(+bGiHnS7(!*W#7W`LC~;?{}N)bj*c~70ZgN0$yEoU;L|M<`XTx zr|0UsPfO|*a$m0T{x1^VpSZ+$m#=`;g?nW>#qtxIURt%;_NFe}W+Qi7b$wC(*{L}k znKz!R{{9oUDRa@=qiG$pyN|v5vaUz7^z6NL1~XO!82WjADmrra732Iu#+z=pxDMvs zG~ID}U7pV!4fBGZIVu<14k=grJ^6lJ(Mq`X)$y#Cala=0*{t_5!M<&d=hEhji@YDm zt6qC>`{-;go~0}GzNjRL{I1f{&(m&qeA&;o`(M|8{j6lsTxs7WHyZ4}Z7T72p){qmVdJCrM+%vn=hkoW z+nVhkqSIhot2h7IwZ+eV?y|XY`tWPh2&a_D4*Oe6?B>5YTkpI0j^6Kw(W@?eIUE0E zhHd`ju6U2Vt@ru*-_Oo7p1ij3vJvwirG3BjVvjA|_~44lrUZ@YLL1a;=s3+lJc zk=UuFJ>^83zt!)?b=Jyfq~#^29$VRU;*!IeerX>$Mw{G2+U^D)CO%WjSi1A*{_owl z;>%rqlpVRnCIE`b*3c8|7)8S9ygWoCy27IS>sfe zXq6-G`+K+dR)ybOvuo!+=MVNb1dmiY^?SYE*QUQBqlC;oX@x zi;gz$%iNxEXM6UcjofVaPTIAw&RQv^XqDptzZN@x?tLn4Q+R8Gsz*TT!sl6P9^1A>8>hGSY<=tb{rL~3us;np8#sg7_2y06 zZFK66)YUuL%hzm{@HD;cvQWiAY|@>hAC7maE5~a48BO{b8Xumt^WO=Vs=lCiTw>R2 zz4#alcix?A`PHZ{+1&Z{_k~ZL_usIr`~3B%>#LiOHtFw~c*)9p=G)^}{PpeQ-)?BQ zYr??56k_Pt9KHFnV$s(A7tZ$toe#vSGQJNyz3gFmk6-SAog%wamj7rdZ$0p{f6iML z?`%v8p=PkU}CEq&O#CnNN}wr=@yiRU}R-NmI{e{GA6k-S!X^XuvtOOF0JA{lq3 zU;HuGg|F{I_*;5HqkZNI+U+%*$+AQHNKGHZy$!j`A5<>45b&Nn!RP;@NsO)+#JAnt zCO+f)Qold4_70~+Gwp)wgg(y?P%IGqx$U^Ph^1)!{V9@Fr6x187V{ME`H}IZy;17W zTl=Xx3-0asl(A*+Cp(t|FCVVgk*y1>v*f$BtV5yiLKf@q#qlZUedG^%Ox(>zc5}X{yK-BMd7=CCUn``4r|{2}g6CdaC*cD|o;d<$Qi7u>AVjgod)bo)z{ zV?cFx)&co9?**ma{M%I!yt5>x^MJHlO6Z=fzfQAEv%Uy=9*+wCpZ{aop+ASVe3q!^ z`F8F9&fA~Mz1dxh<{ZDKDCgO0+;@oEIeFh+z1_R(HYcrQkh%KwPSrtyc*#wNIdhK0 zczu>%F?YfBx4PVZXDtuM`MUVuNV`=gbNR;Z}ClN^ocaCb!@CvIFPx{_GbAGG*44Eeetyai=Tu$heV19lt1TCJX*tgB{tj1v?lVC z+^y`7Q+NJktXFrtc(tyeEaRKZS|f+w{_;M5XG}PBfA6yMt~P3=7w7+5{%6bnw|oha zpR2!Y`g5E0hyLYVheHlFHvXT@b#GCFoN}??eUsuh316*ytDSYSrI=Qf1hY+;eAM}H zoEo#Z-qjj6d6$o}lmFFDGdTM!Y!XvUmr~5t%Xtl#>JmfEct4fz-2QCt{?ebkmy%N} z32^K=On)R)gCu?*R8DxnDwj5^PJm3`)5y2X6TyD3D~jrXH4VH zmS2-5E_l!LX-?_X+2s|RPh9zNsGjTN3u{xB62ZFA>RJ9@g*MO3V02_)U<%!PLB=VV z@xaToUvFyH`bH$?7^uDIZ^~M~?Ppnb?h!N9@<~Ova<~OnU)e3TRG#C7{D)*eAMV}S zAIm2ye3^AmGf;))a{9&kH@hzO*O{M<{=Z)%V#C?X-2V=<{*V{fpHRYR&^v8Ol65DW z{JR3x{(UmL-m?6zuzz`R-(}s^|Mmr0zuvMl*WHm()TQ^y%l$_e+}0KAn0YvmclOuo z-NDBB2j>0KR%%%HbAF`$XXOPimm4b!9f`cMQs2Qgo!@Ky^ccItN!6Z9y^4$@E6xSY zSm1nGpryp9wJLmGE^|UsYDtH@?Z3A!)^(q%a#ej!XfgeFykc}FQbKPH!^0PxZKpfL zSuFp(XYH`Rkmk{`U~Ylz=VXO4{kMNkr>jf9joZ8Dv%2e*nCT6Bjy5a}S~<7$_??;h zTEX)bANF34{l7m{F@%v_d(G|mO;-iP4!Bh?ynU5&Bth`L)XW9Grp$8g*Y)>a3$R_e zxux#wmv^G`*FL^}|FnbFaeKAU87G|Y-8$@l>SfIgUGI~763<^=*&q?NF!Zy0WZ=`J zkGJNPUstaDcux1#nK|D#Iq*3oto?Chf2u|3wApGL)l8edZ7y27B4_jTvq5)?6LvVB znq#CLI_c^kKC2HeWUm5a*Hc_ynOS768_0NwsBvuI?y`K4f}#+L9YBEqnI2C_Ge* zvHHK_yh?=B_qtS%|8Ji+otY};t1KwX+%$h?TjleW2FKLqZrSXx+Hr;9uLf7StJl}{ z{eAMU^f`Z$xWKf0z6$Mq^_9ok`5NA(b#PvaWxoGU=#icK{qr$QaXZ`0Q_ua+mz6lV z-`b#5cKSWGjhxJRb0vGPX+OEuHM^N9cEI_{{Quo1DLDsYwL?GDJEe+NZFwqv z-0YvigPa!|KgaWgY}zZMza%JcTFsAjc5_!Mmn~4JkpT3 z5-)mg<~@6+6NkK~26$L5$a2U$J=gxhV#h~+=9qt*U-2q)U(yDr%+9+@4_ASOAb!@JU7UJ@A(w&_5Y{xKg|zr{IJ_i->2U1 zL&ZNo>H6U9M;Fig;D7SB>t*#HPIEr)@fS8tJyh&*{_ljASB1`;U8~nl&8Yopwf&pW zmaI?h?=IB1r(WMs9sc7%(Ncpy?!VvqZz|Wb^5_7K|AkH9I(T}G-bMK-`F#5C>UsBQ z7aV+ezIV&de=3jmFh6|$?!pn5ig!)X(lcKlF}8Pmm%EU8XYrNe+Yg&$vAM5J5!QZm z=$o7UBer8DN9?vU9dei|r1t#mmABvDpQ@9XUis-X-@1>dLMA+W_}^sCqgPegm-SxU zdmQxZW^etg8OJ$x&7U~=o@cwZf{Rbr_ba_K?%s{HeBSx$wYh=hbgl}Y+2{JW)Qux+ z{g-7NdeXGlM=XR^Ep#>Tj$mP{#JXuV)K<51j3UdtoqwR$%`^8HtzAkY`Hy+Qx^EsrGa zBd0cB;xcbpw>am>8rYb1>br#k@Im-fBu5&T)(F;Kfv(t(g*Hb3yn|vD^ktw zyJwyW+1GBX|2O^XhYRu_MK|3lyT@bK*njI!c;MM%^XGm#Sao6nqnZ=<_Ni^fEIYpB zPK+L4X{^Vee%Y|NW!=pr-4FRzftSh`vZ+3~zw^fIEf*Z-ah;Y~ zA8&GztyP*^{^?fJc{+xBRO62SOqNmJ`|LfJh3cQ@&-QHn`LFfVEz((F-c?K8YF`&yGBMz}phEdi(Vz{lKGaM2e!cQ_mu}C>)3q+??a6z@U8)*|eyHF3 zc4z0t+hx+ByML?@WuNikAOF|qfxJmmzGpBUy-~U#$$(|?ZMj7@PXpDaTs^;P7u)|& zZ|`*czEgJQ!?XpnXRTSx?sYfs=i|UbrAKAH_$KRa2@zD)Ut$$~WA&at7aQ*Tht*EI zerxqB<8aCMA@1C2H{YLLzJll0f%%L2o_;@gS3sZrl1D}L$^?naACB)cUbXt|d% z!@ANH{}p}z6*uqdU+cYPJ$L<*k?qaKvU`!o$X@hjT&$ zM9VwN>-KJ{eYmukDed^1dn<&G&HW#JS^aBzqXbb?-q5lNZWd^YB`f%M|rEx=I|57?+>o+r4+i&QtYRh%K zzVzS8*?O14bjm;cH2(Q*N0i~3ykPg2qJbgl&pk`7i#@Cq@ALlaCAGM9?s`Y*XgAsW za{|I6|Lyx*l@JrO?p|3=@L#{0DW$RJH=KSrx8gkSO3$C0C$BZB*VUNpDssuf=Rp1S z&kVK8ls(lS8ZFa4x*?D$^2<@pv#KgW3pQ1#89peVX#Gm%d(BE!|LMG4e*-_e&S#U_ zrDl+Rd*js!CQI*CrPx0Z`>pnt@zwV25|(RM%?vm+&urEQ2XDbgPbTE3&di$Ie()^k zu8qe##2JGsk1xOdj9K;VPVS?r9pxtbv;REQdwah%?8LIFuggxai}XL|l$ZOdttg@UKL71oS&V4Sf{ZgRx7yOyRJckX`uIF^{jOtXlb+pkd?S>x=jmjwwJYbJ zF*vtw=l|TjQTHtqekRmyUZZ$&nRe>2JF3@G-^l*^oBa6QRpylQ3sqJuU-mZcVt7AC z>9KoBGyfk?)~s8z$v?EWX+5v^3Wl)oTqlRu=B=?xNyh!0+!YVET=JZ6 z(eN`M>fhvppQnC*ynfduw)?#&Z}vUpxpd4tpkdXnxnDQGFx|ud*s@l**W}Kw2hCq+ zO|mllq?a!C?DxMDhnc;8EL$1XDt*AVd(CnE1Ewa&{by^)74uBYiwHlM6?&oM?CyeB zI$`R5Z#`9B_nN+LdwG5L%+m|YP0w%suDRp?Wr^(H(^FMH{BKH~`XQ5ZgMj+J1$qBl zrxrUEo%^}DOhom^$Lq($f6bk;c7KjuZb^4kc}Qupbcy@-so(Uh3}0D<=J^|ZQGGg* zzqIsl+s264HL9_`H5xV*FWA_?9qNZ4r-kIu`$U}vu4&VS92y_53YYj z7r$pMP+k+7sBQo4>oq&Iw-v3t9*e!{qJ=wyLiQ%jai29$%0h)>qH9k4+1$yy z5BWdZRr|$s-kio0f1WP>Us&D!Xx66B8L>Y!YL&o6Bg+1sQzL-`#R$!uu7gGH*<+cKz|OHR+_^i*38E{0NtxRp_wo3fGTqW}0$8 zFU|eNJ!|2Uumk55|7xC1&f8F>=H!$2@cF;LYj52uv2?0BBQF7n6%un484_EwVU|@fy2W?Z zeqMmV_sTk%*%iC$H1rj3?MigIYH7UZr0;X7AFJ27yi(1(f3;Jpe?3d{T1!*8Ytdp~ zg870M%Xx1Pjr4c2-}ui}&un(nxj%p2zW$&(U8j?8x}TeCwEv&5*~=?f%4ckxw{d38 ztcq=m3(WZ!wmP||R~DV}J-#JhcFO&yKNfn-Sl(f~r{nLQ>C5ijsIUK8aBi)C>C5M{ zj1splem+O#m*wkMdJB&IdbXx4+>8Im<{9l@-bcQyVm_W8C|>*4Kue9|^U3+^YR{^b z&1wIfV*0mYdHRV(r}`eA>W&PGR%Pc_J(tRo@#C?G`Dt-Go4d^yD;BD3NIp}>{@~K* zbDch2H<{`z#+ zS$57VduAL@{;)pn>*nLN-Zl0b3=2=bdKa7>(9Za?V`*#oSCt)8X0fhW(G^!5bZ-CD z?+cVGG889lwGewEIqhEWuG`0cZSpy1D*EwIB;U0F1H}W6pIv+>7GftT5NOLL{jR9~ z!-S(ZS7p50Fymc(F}LG)(@c}-2^&;mMD(UDVX7_Hv*6t}bFWHh%-q<_{p;jrJ=U21 zC@A(<`&Mzk%+`Z=UAs zf0}f5andxG)cOG4OaGi3V;6sGj=sOH*d(PquYRx9i~?6rE5C>bG7eWt7ba$JbAM#o zIdk>q7Q17$ol_hSPgJYyY|q&*cso5S<&bTZ_O!TQsY5xp?Du}0J5Q^w<$n{;jN4^v z#a7hZy>jQ8!t-mDbNu(I_&Rp{%6p_^GV%SR6HOL>U;UVDuslPxXR=AqDMdR!B~R|} z=eFhtK5yNZI_1Kv-q503AK1(;v#welHAVO<+h?Jw|5GjhE^VXi*8H?^nF`BoIh9benyQ2)v_H9NJuxTjmTlV@v0pJ*#j zN5eVUGk>@{+>`3NvzNaxi3^`6xU+Gg#lf#@*J@ib@LS(0rHax$-TsN3LH^#htbPwp8>$ok~CJmBOz&n;tUp@$L8Dc2q9w z)Xw+$deQzLf4k06x~k@u7ok4)dd1{ed56}%&Oa%AAy;3n-psegzDv}4-|Jtdr+(i| znD4;&biU=>`|8g(7jNi4@zOW(a?20S!pGn5J@k-?sXdkdX8C{p?aOwYD*F3kdu>x= zV4ut(Q`wWU3(Q3?ad)@(I4{31BVw<4UGe2n^X|=WyaYFS9W^seK31KRc0eWM{b@#l zz+Gu!GvBA@>@QuuJpZuQ!KfJ$Ij;IQmOCYHb}B87_@!QaT>q<6+1J?OAP(z{PSdaN z5suEq{!}MyZP;NH@@k-E^TwdyC z;a8-JJ6bKSS5LAOO?_;)zeDT$rl_o3K(_c|@zfZ$ELakK@qmIZs=XZSEe}woC2v zkCU5^PW>mn>-33`Ge1^J89HC!K0foqs++SJCq}IjcpxnHXhDnCztn#LSznd?*4$so z`KP6+CXVCjMn}Uly5VzQl~-6xoXprG`CvoAZS#buFK2`}ELCHAa7$*b;qJZmKdz*_ z7h3gDTK~N4`S{`;`cIr6{3)87+c4!?X#1jxAJ0U)&hS{qSs4E3_Vj zo4Tr3C`*ewi`HtDg{u{n?$^nSY`^1QwLWL|L>m>3pwE4Fyg66$zrEfQ!QR#dRhGu8Tn#IyGOwGokp=Sv>%_I-8sd)4K+#SC&D*%N9G=o%*++p+Ey z`|Zz@m`j@lQ*C%}*Mw+ioZD^5H~sN@Z@b`|yFa{-JXmz-WnZ7KxzZ0vEf?wxkt=BD}g*oc$M@A((C`dq!A zVf^NM*5hpo^Md9F9%657dJo$7pb{6pZ=Q$JJosO{KKu&`1O}4UEySiIV5&qsmATQIjUbCoR0EY;B7PI z@VsqOZ@l$6qC4ztzvR8DaygA`N-xA?KU@XwjvY_q*u=0TWJrb(RcFB`+(PJc6= zJuppsFlXhAFOLq-p1-DI?$YM1ms6X{Jc z+Kr1{C%`*tqb!Ei$VLx+d!niKV})~+r2Y4UaE z{!5PwZj|X|E~~M+cx%Jcj6b=Jmw$-;c(q9Vz$?xW#@z22FV7xMzBGU5($_pn_2xy~ zi<7f|ed9?^O3RDznybmTc}B&gU!Pj4niaV-9?V>5y=rYb`+vp=9gmD3jGKA)U9~OH zQ++v0Um?alFSB-1vKnjjL`Q}l*_xB58fiyL*5)eoEvs_z`FqahV(o?_x1L@9;4|~= zkL&+tOf{KO$YgI3d$r}yt(@w`c6$3$-Ipj`{butuwY{Liw8n2qqse>Ig0~kc(uy{Q ztkz0ooL$x}`8Dn8-NhpJeixm4pVl7OT3n-kA?Zuev3D0bB{f*jiZ(UniNAN9JjLp< zd2xVj(x;rvc=l5nkDdA7>kBXV zFYV(0DVgkMpIpPS?*-L{O9Ir?)c>$By}?lmyMEO?*|wz1d&#c%S*v8G zWEoa4{;l~u?S!p|ID?JFXO$PXeLin@oL~3s(b0S=CH8 zEsGJquW_Bv?^UoSQ{jx0+O2+lPbI{D$?Z4IuIKsXTTuP{>ld%DudmoHza>6r&tJ`2 zp`xXS4{gor-}E|h>nkSS`1v0W9D1nxe)k>DZ8u}*Z=F!+(0!Zj_3|aw>VJ%-*XL`q zb(-n;W~V;Tub=vHZPe$NwFk>1ljfy!mT)EAo+;wauxUlw)ccg%lzJ8JKP2ETnq zSNi|7p7mY(xJNwoyoR(_|DN_K1$(ExIDWYQYkRk**Vh`~*{a%my*?Lmcif11y;NA5 zzt;9l>0a)mCrY)BuG~CTcK7r0{ei!1tz6T#EnQ!b-Co~!;Lw@nuM%0)oOO<5#nYa$%tKS<7aVHYUvXrc^Nw{!&IvttY=51snyB$|`*MAi&mz;dMd!+PKVG}e zq$<4PUX;zddy=mff1R*FTW0;*@9%H@i)RY5pP8^;)}+DS>%apq9qBDjpSub?JyW}` zuisUF^Zk@f?W~(bb0t!JbdI@tdwXB}Bg1g~_tPxfBNm-ej$7Jeq82GiKlJ_KeCeRF z=`nZN(3aTSjlP$JxYw-h*~%-~QI#>{KDUuwhO3gxlWCKlaD5P+y|iM@*$2;_)JU3X z3Y-6OSURsn)7UETykWQDiRbrju2X;Rm{h`;Wf~fjoL74|Ms%;3T&`2@lv&xI8_nMe z3%h<$|FOztdzt_JXLEn~cw7?pzRByEFMFbk^~lsFmFT_FrTmt<-*%qSIr{KEe>n5o z(<_wjm@PiJPg8HTzzjHDpCIl>*Kf&a|&La$4=FI;R?L7DCgpJn@ge4|FsqRgB zv#sjZ3(wyd)?8#|KD)cde9kXrYgg8zL4Id#FL2jYs6O5Fe8Hu|AKPb#eiqYKVqX8A zcLRIv(H#fie9&cxJ@Jr;&$nH~m3eT5E1wWOW)RU5tuw15- z_r;yZB~$qr4ojV5(34G?WZSV%g2B|7-O+8z{>QtDDmB8hwyWJgE@Nc0cSiW}XE7`h z4_9xV{U$B^(L9?KHa~Q0_nPTnOIYp1J55BPoPmKUhOcEVM~C*C+cn4dmR+!wxq2lt z_Sp-af|Gwja%FA^XYQOD;Jx;n+!EnDi*=l0-&kdmBG`BKo(ad>sEy3eYhdEE=cpF2t3nk|@La_6<+{k1D@3$i7}SqWW{;m%(k zn(Q{;ZhFu=h9k)y_a(d~tGOMzR@_=>S+=HJbHQ@|xr$S_=vB0TGF`Cy%x#8#gZj9{ z6O$cku5E0pJY2Nxh0gsg$EttJ?pUK4xntGRQ+CbT{ihjk1XW#Pzx3_H=A&zmc~s1q zerEY29rwa%laH5N-MhqdQugdwbq0w+btzo_p^vv*Q#{GKZ|;$R7gf)t*4k??s;sEk z(EIsUYC*7JyCsWNHS@DQv*TUPh=={%^21^ON6xN);$Ef9-ZQ(I{22LmIXo8h3SM6G z!AsU{W9srb8OI~UmX&SNbG$8Z`en2i+oXQ`eY?*57B1ys=s0t5--WA(mx%rho2zcx zQ2*K@e!b%ymn+`K)be~?&!@8f&2icDNaS0*_E)*BJUavL?=Sq(y*?{e;^MTsTOvzO z_}>w%o)t3H!zF6wk5vDA2cBy5g{sao>$P9A?x2?_o6DKNJo}mcdb!KR{@JATJX)vO z`+ny7Cvy9i7N1LRXw=`k#paY^bJz7Qp`s({%2T-6i~9J_-723N>%rI=)_-kPb?b}X zrwigOlszVvW`9ha__WHiYezNTHMQ1R``z0&7nf`8iJG5ob;`O&bCrr%?rL?5GVzy} zSJ*!I81AvTzr=R&-lRWueM(Do3`5qO%FGG7rgZl2gtw~Swr0H#cwhGC$MQt6Z6Bv- z-VX9Cc$}@C6t5PbdeP7GTGYukYj&>xxFD^9>9f2Z!%T@&69cZM{GKKui=wna)*WHImDsBO=}i zy%FF3XIIAk=j;8Wo=rRU?69!9RsLz)b@4in^uzv{PT9*W9aJ+Zcx_=>^Qp(WpT&P~ zcx&j?#JhrF{l$hI?!JuNS3ip}PQSDD>+vQ*Mp*`bt9rRQtK&y+Co$YJ6U`EnThgkf zVK(c$|8AL(4>uQQYrp%Mx3tjf$J@V8w+l^uX{weg%xCaX+|2fjxwTbNY|g|Z;+YIw zx^>6D{N;Oio3%5aQIyGd|J(Z$740nUR%C8D8g#1m*t5v^#=kW(j+|Ev+pg)ab2g2A zXL{uN#0jO$4X1uumx9j!j@`21np~~Rv}1{3{Dn2oo4uPX7axCnrS0bRmM2;%Tr(~m zD0s?QC|UMaV%mPc>TZ|iFD0169z3Dy~V%N9<2YgzW*JY^)HEUi)!k>eR%sPYRdjwIsEVDR+qgE;$O%5 zzUqghXy&)H=6hLsJ9NWpf_C`o8=Rh<ZXa-@HCA|C)8E}QZ637|JI)U;pYYKeGKlnGHIGx?4-h`oqN{)tnJcfGe075 zX!fghk9?P}syLzddf&3RwKdwFk6*06@}TEi+YEk1yZ@pF zqg{fmiN4o!hEqE%q69_vq)Bt#wOjJ*xL-HBa(;W6M3?_Vz0Bnw`uH|)D}H_=N@XvGfPu^T%eMo*4RGyLZhoW#jT&DoZ{s-lo6Y zNpJOrs@`JL$0jwk?0@o36)uy}KH%WaW7d)PwomNz{?ge(*FFWZGwk$O(H+#1oAu=) zkI||#RS|#un=a+d?JnRxG~Mb^_Jq{frxrV7_@-EY?C1Te|HJHLj-K?Slt1g2x!v4e zE4Nc*`;jW!#;fA54u1KMc8-rIxW4A5qV3V!pQIW$=}MCK)Sz({7hNKlChNz7I2} z-`jww^{044e%N|_Zrr~1y7IGkXZ#E6WUHTjj`oi}H%mus=f3-grcIludrGw6iRt=x zIU2g+{o8#N?saha?wXxDbMF@!>62GI`;7kG_57K%;L^;2Zp^o940eGX6e@Ts)@apvvrE3f4zKDwy> z%vNMeec{?SAE)?BN&JsAJroL6|GRK`gw{E=7c{VxR#e;*?Zmfa zH1s@~tCQ4LY;pi^^FtcI$~1i(ajEpHZD7>|edanxlTRbzx_`!hwaun%~Bb;hDL z=STN=9B;gQAed>wWIfMeyJqwO$3>gmWCc}~C%%g2znW&>b!*Lde%vM~Q~ z`NHN}o8HCAiyZdw870{N-CVcodROF!jEzrq&l;ty>sY+>;+D1ZML#ch{QY!uSoXHu zoyRLbhHt)krR&PQBD+WbcmA5YMx-(HPs{qRft4qfL~|9BL-~0UtKOw8d1duou=hO-+ns&j-ZZFc^ zuALX0<9S=Dd*;Sp=AW6atSmal*ghqxP5#?9)6!m@7siGLEK1YXw|zd#|8uR7L95VO zgDl^o9cibsJpZj>ycV-U=-D#SLbfm27M^5{Kdxxf*uQ2#pWXGiYWy>Y*PVFC7$7EJ(o(;TwrE3-I zI-6Um8-wp&Nv3WuU-YJbu4qwC1?D;Z}0Q< z%MaPKEZr6cXT=pJqC4vko!IR8fbW2TcJlUT$}6r<{(N%D{R1ZtpZhErdw#;R#WPoj zS)AQdaOkO$=;B8ofB$Tkcb`#q`^{A!sjz-&`Ib_h9I?>*b3(Kp=f zut?Q{QM`QTj*G99>gUz7PD>DOk#oD%Z{wQh;`b_K0{`}l9-nq=xoq<8p>t0p?rs&SwzMg-3U4!-WjoL9sEtP*}chC0F%lgIp;YRoE&mR+)FfcI1bN`C4 zyzwbjM49)Yw2tSOz{`pgyX3b_Stxw$?ysIjcea|W3;8iyp?LqXjgz&fOGoz_PW77n z?bu1*+8|#ipKTVo4ZCA~&QI92_r{9l{&Eu2*~?6h{XRPDeYu2aS^V0hmWzB5OIO)+ zoxOBu=XIB<8B=+AJTnEJa_21FIw#{*(U&A$*3!cHx1LCP3A;@QT`6n%mpP8y;bZYZ#mhjtuAM(w9ENDK@#$=(`sdT?2Nt=JS zKX2b_`1Zz|v!`OJJ{Y&8FKYg}G}mRz_LZf9xell9T?p3{jamFX>UZ3R{U$}X3#2(` zZ4z|f?Ek-KFVF1%g>Gl1;(Z${*DJmHY?qKCtS)G4d8GW)r6Sdb@Ae+F`uF5=tChac z>H5+I{f8cH^7+rU_vn1*H}19!-ckEz`>)H}Dg5d8p>=<@3jC`PH%{D}bcgrg>T9PZ zKVP2ad~Cf<%()xJheZv%#@+D1p>+`TRty<2;i;^Df|20*}!%yh{GsQI4irXd< z$Es@&#htBwyX)wM3j!=|ca_;b3+T;m$Wqv$mH&0^*~#1Q$g+E^%e3E7V{SWlgX^;i z0Y_h2#-7M=;Iec+@vCoXrhQM;gei00h#Y-#P4?kDyYD>z=C0cHgJpvGJY^nBg`Xdz z(_Q9fS9y57JHPLF%++UU7CQ(ft7%C7@i*o3 z*T1r%oA>+XxxQ7`{T+68uCDu~-96X$O-~YTpG-P4JzprX+ zd-^8MEB1EweHFa;+4U=$&9$fUKC+&1&3iX>*5Qxe%3f}MT>CL~$;#fqzC$45d7J9lU8+6jHB=bq{r%nfd>6;oowq-W+}JI2j6?L;SE=QZ zAD8?%>c7wXyxwHb#A8jG_p+Xd_M7sYTWVDQ$}GyO`GEJ`Z|WQMt_cdaa!**cGFU%; z;u_9RcF6~Km^^R$)8NPOMI`;UTjs|j-)?)#XWfkom0;@EOf$*S$epDBNWoc7$R%_7 z;_cCMrS9!k=R6WwdCWH=>(|;PTg3GaIUGwib?X1N;~v*6?g#tC|MWb39sg0-E@p{N zuxIYJk7^TIr?)=&$U8Oq^M0{NLyPFl&=C1~k6!GJ?WkbZnJd0hJ45~g10!4dwB2WH zoG%<-`REZRqqw_b=(p(dSJ%G(`5V9`chrRY>UYbE?}32=2hOD{E!Y##Yn%J4@2|p~ z_c{g|29A9@<+j{hv66X>Uw_c~tHKSnHy!N**8fd1oLF~vx~{Ep?x&r87E2$qOC9z- z^*AQ!qM%qZXItMoD>GS{>gxC?hOocEtciWo6>Ghf)@D6qU|>pk&CS?q`_@_G=JKM6 z&mV*-ukk%Gv86`$#&qTR+h1q=^VGOz*)!ebugH<}FS%rUcFca1{aoWkry)LdXy>KOe(vtZd?SdSBJSVnY=CZ$g zXZ@=Q{kzUBH92;CSK``dW>a!abN&idkE!*4`ayqoc zyMO!2=#2Qs6|Wv%W6zh|xg~eyF4?maWmPEq7Yl&Ji`8^2QJ$g6w%|K&KW>iN6u z)-$2x#}C@suIcl?a6QLaZ2bA2vc=D!pj&AhdydC4pIImwwe`_+zI9dQrWcRhyUdkv z;+fKJj_Ru%)%>5XXWz`z^4sG1&opSEh29mj%7nkOep|miYMOq;C~A3<^^-gDB?fB+ zEAsN>ma*UdV&1wp#7I?FUjF+ZhKeser|P|4=jP3OG5fXFvNbAa7wqwVv&FmO#p+ob zKCX_vzwlT5r%AW1o^&tXa&=je$VxVGGq3uSUVmkce)lEn)o3~S?RjJQ!&_RA+xE)t zla+Qd(n}b+**b~^uRrmgo$hDGDJrob`eF0I?+jl>n|{kJJ{hS0?S{ztDH`9ceV#fl zj}BNX&sX%RE{mVVF+5KuBdTHf)=PTjnbLvfMqTz;7`5YUlR_d4{`> zXI?*2A>$bD7sZ_)EX}$1!ZoKmC*$=ETZP|=+I>-ee9vFZ>a}BmvY_YI++PRge$INb zx5Kt-&BqLZBx#1+e7n> z|LS}(mb-tgqjCC0n|y93Kc-aPU$;JTguKn^{J6-gd&{SN?H+ZD^RJy@*HUhLzUMy&E^=m7aS(P)ageNAn8*`paJbn-y9k7d&8$ z;%Qj?`~hdj!TXp5LZSjm(!lybeEx7xx|7fxC=9JF< zlzaC?og6NjUV2|MbwYrSgQ7_EU-tgm=gDT-yG%aKI(ATY>Cy8um&w^~UwL-@shLM_ zJW1MfNM27%(D&n%=S#wD&d+(#5__eaPuKF=>iO5UdTU+gdKR@~ev|dgS0|Yzu7+z{ zuD^ObcbC@1RhQ%XAHMn>sXo>9S4q3<)wyMMKfb+|-{~n}E@vp0EB@Nn^O2jgvM}Gu z4?zo?xr_7k14}A>`Xf9J>+;TUy6ZQkTl?@{g%fA0<)++yvMyr#`L^xOEGpr@E=*kT zd5sFcMeFvmnrz9;XFa(NYXeIzZs#xEwr$&-N8$XB_7@Axf49c`jfr~9hewGMz8LJ@ zlA0IW5qFR0{Bn`&Gfz!^v?qk;_`d%+`zGJ<>O9{ja{bKVu9^7{xODY;6aA+Ce4+GM z)bz`OYua;uK3ubOTKwxPj@7s4)HM_BZ|nbxVAX*>zWLN4MOW#83A! z-Yi^v#4PDv+?nv(PJ%Tvt@B!+NtR}s-0@o|u}()%Ty`hhHqRT?8mhjF4hQr9{+ija zxM-i9jHM*A`Q3LSNBY(ZbZPUvyxjNwb;djK`|sx4HU+Bb=uAGq&f9aJpGmK_WZ%o< z*F+NoqMSAF#?RTiXWh0_QActnJ8^QH(CYbHm=-r}(~Y*NSJ~|Hf<*hQa(WC_FL%in z4E6NmG+eTvu<*eA9Saj~$E^AOEM4|*?}`asC5NRJuUc7naFSJrs8;r^_s^oVA1`7* zl)i%h4UnaSK)F+ zF%pLFBj0tn>FFGdx-PH$$uuv#jMLQM%gWnAK}-8yFOFxt(U5TC*Q)3Ku}93-YGu6& zowD!VjeF;=I{(|UD_-Jr%DMA49UJYY-pXyQ-IuN4BDR)m$NM+xCY8nAPeNb+6RH2Z zk>PD+>{FwC$EsgDM}^M)@Z|O1ujQ6bb!VNf-@!rmU#!ylgn>?e?Q) zYTK)B@opEF(VZkEUcdftM^pKl@cfLR-$GqpTfW?OcB{H&c6!I}RaHrQJhnbDw3UBg zZV`O-K$URl+1WWe0&1QyFfb)8`k|r9lfb_0OXgFt=3|xu>y|#t{NTBr@g~)v*(rhGdN6)r? zxgliUmT9}2XE6R^Oj|E_JnzI3@rrKsm-DB0O+EVCXv-6^@|63mX%qD;wSq5HEAKz2 zS66s`&%_CvIs<)#SKXF%o*Vg$CGGny`(uU50v~R8e)>~`%9$-}dq|bD>HLH9e03W|r?0xWeM?x_w_|%2ilj9~@Q1H_C~$38=bl+C z6NTS=Pjz2eyZi2C<$E>uy8Cv>mOJ%Zkdxz?ig&0YmZuzcJh#p?y*OwQZwHle{gr{X=|1> zS}Py@e0Sx`I-7VU4g25QH=3+Cd8LNWWM#Cx^og%mvhQCti?ulW-8OyQmw&g-%zoXu za`E1gj8*g6ivB;SJpPw2AT#4waiC!R`!{WGmh$RzOmN?QPxT3FYt&6`1HM-$9xVC) z{n(}Bd#;ohSgxD>t*u&Ji{*r{Tws%(aNgS$XKiLm>P;(eEGaAf^>5C0?$m%i4sU8E zMw!<-1pMXyfUv}dDtF`Fg>$g*iMXs}?y^&I1)~e?2C?09R{+q8stBC!ge$|0q zbNj4!*(cgB^-ozWnfYS#8^hmjN9M9IENYW|VJi{#Dt((>iu>{iBj>EsO1d%8=k`BJ zIXZvM_og%7T(h0Mj3f9>Hrz~EZ@A1-fMsIgj%yi3Q$Lij{IDohbXM~fxPPSn@3(}v zCz)5TEc|$M7iV*t_fu`t(&dcByZKsA2Z+y3>0^KV>&$9_3)M?oU!TczeeJrp;LW7H zqRAO=Z+ySKRK~~h03+LHo$Q?#`>k%i49;33W+z*C%ciX4Q_hZ&h?-xCsgbnDmd z;HU4N-u^xJTD*?`+gC|j_9S1PAScSXTldMXMWHfD>!MByub*vbCzigZ;m5seyH0oZ zMDwVtI<9F~>*r5=yKj%T=7N{Ye(}$5tI>N=RivDD;??1+FP2SAV9(wy?Hp_L+$&n_ z%h`LXGxYA(U+O&iCP>^>L__x~_hA?D#uYi6XHH#r#eYZkyhnWZjY1`7C7zmm|7>Qf z*oIF>O$66myQY}-U}hgR1#Tv3ppz@)r5`{J*sj4ZMr{BCD2NqhbC>?+2S z+cLL{yxI3UJD)^R;=FZ(DVr1Z!6oo8P>4KKbBhpTV()8n67epF6K-Z(Vi$)#vjYvKbcyr$wq&_9^5%aQ?X1 zTa?3l6ZFdh^&~ro2_Evwg$IjfYox z@7$)w6`mk}HJ|_P`JYR6?D}_R){^z_HcopnFIAEfQwPjaQZe%E9r{Jphx zb!tcBp^DvyZHr@*t}Ns|AhmTm|3BuCtr;IoT1+HYy}B}W`HYvLp=Ab%cW1wEeQo$d ze5J&(%I}L$L^N=J@u_eA7JL3n(4}tALmQK1JQbJptlZrd`sdn*x%1y#Gqw zduGk*>1=iO&YT~G?@zzJUok*|MauhzY6I7+@_oh5rAn^}oaODL+}+3!ChprnhgrJxlykbxAST?}D6HF_#${+p-D_tsXg_THjFV z#PmZ|v@ULn!~7#6c6mP^to!-qU{&qe)WVLav)&(GKGWei_F>-YkXNC-^SA9xd);}j zfay=jrKA-JWpy*1e;(Lv7$vP6skZNk%DvSoEsC2eT8k^i>(0&C#?@>SSaoUD|Ep^p z6My|+6y316OJc7;-OJ+eV;uDlUp#&_@%YuIJeyMyi$#xrIllaPgSNVuuN$l0=U<;@ z)S51JR7u});cl|2v*pk0R^NJEZ{_7|nH+offpE~?>$Z>hQhqPhjn_^2Y8SMNIow;C zHk6TpN3qAfGzw7=K0sHBvz9(~EUf(nISsKII`F@9&Y*%|= zaAIcMIp+nnm5Wu1jt11OY}1dJGOcWxFtZvr`|LjEtMi{dsql$Cd$2L?S=x!ba*%U-idjvugdE5rSykH%k1RW%a&T4=9GEQcjEk!BL-KeY6_cNO*yg9 z;eFTBJlPn{_&J{>Z&p3tS*0raNig(^Q)hx%g;GkZ&xXn)8mo8e${o7N@^bSwmT4=# z3p!`$*UIgQxNE;EVCna)Yxe6-yTxu=8j!gEdH+|Qqk9)mJh-B2a_4~_j{K?7w_Qv1 zp6=?J|N2aq{-;%IINzC8JvRC`@#n-zC(S?ew{Ch7FLH`uW9u~gxCZ;I)PFToPQTuE z)RFz`^KV>l9^d;e(Ys`hneXd`MrS1!N-b@RTHoUEFDUa`hs^Jd=KI3?pPebFSF-a9 z%*VU^yVC`EQY@+n~zzX zIKQLpaFX9XUqSDsRet?GuczC)B~4K|)2-90vFFX9j@R00=LGKMcbt`u%3QP{LDlNW zG=e~5B&||x=VMqMDHB&79AM=y%e7fCZv8qzl z<~@P6znnwm4)T3$&TsXy=WZ&|?b=@GAmw5GYuEidH+GA#E@oh0O66xRzq8iuZadeS z5>4Ir;x23-AM&sA=}y#clW+Yqq4Vl1)vJ6y=5Efu@4Uno&Ty7is}ttQxT3tK*QfWX zYwy1)iB}%XoBhC}S<7Vp>>uKb_|^6tt7T|f&|;#n=3nBx%Fu+M+wX(k$~6_TD$S@!Kd@DfW5d8K(JHf6raC_tvg9!&O&Ke7R;O67y)<+x)`a zVcxC%XZ;qY3;%E5in>5%~E#h;P!dtWt3 z{=2N`sBr%5tgk<2)|g)S9nL~nV+2NXh?nOnLxTYTBJozMN|D#R4lNU6-nsB6O zkC9NCxM`c#^=+#cN8P(L$v~%7w|wE|(BAE$ipPudxf6x4vx) zW{eLJxn+O6%RY4eO`A}Grth8Ko3Gws3|SDtb7=2P+gypBg6Nz=PODh;m1j={m^1ok zM2Q~M`#Hw^uXFy8h4Q>W_nE`t~umW?k1iowYnB zsr|lJ`WbeiYTJN$o(f8l;TcbzT3#LXX?%WgU&HqKml8wXFdPc-?fUpBE+rsFW6{#y zvwPEyow>Gm{%n2Dbis4?x9v(Tdi?!c$g+Ez0+*#Z99nVk9!HpYk7#3zmW;LN|7M3d zVWtV+15W?4UdyPY5L@#@sAKaJS80<>y{EqF=g_;-aI=pM`R_tJTy(01Jaf868WdS9#<}R6WGyLpEUd4l*v9?Pd&N^Rk(up~u zG`RW5$19U%-qkg3l@T(obw7S?CjZ&0Uv;D&Kxz z!hHPFNiRR?AM8iMSI&PLw&qW7;Y$&Lo9C+It%?;IO*a_5ESTBIyHcC8Ru=DKS zzS6=>t*o1w^$*vreKw&ljrC{5j+zY#F9q2Q+Kzm$*D?E6DVEZ?aQfGWDPp-A`mytR z7p||?*nd#XDk92G=FhGt>HB4Lj2-KrE({jP8#mD#DI`iw^qbKW|q_;_j84>h1~mg7*G-wf@$W=z!IyY+d=IGHx9{|DIvi0iH-xm;a~gE+>l$EoU(6 zIpbc~@qEgu*&%UlFAvGrYOUe6I>zPEBxt|r)QU$Dyql_+jSPET+6JS<8kfH>#!E`AGkwo9Ba ze|F1)b*zb})`_2M^5}G%dq8dC(vm-4x4H;yTYdRNYW#{$Hccjv2Vq)azTys#CNU?P z{S?+yQFtgX`F;DgEBh8z6hBVhVzf{>wROX{Z)-0z-?W@<^my;d8%;Nre!R1pwE6LC zQRma_jQ=bnqR#B|U8Wsx_2J<4q;tQvui4A><}!yNqv0{x75?u|A9p_V=iV+C9nN&e z7gsGKj5&jh@(ooRPk+By#WKBN*TH!jp6a{JNUI`s#BTc7{@J$**H52KLBq!USwb?46%y-i&i z-l{Fl_1-M5LB;9ksyRH{wisNNc)WUPPtx%qC-(Y}clc6Ve)T_JF~{e+y5aks`{hdX zY&UPS?Y~rHx#(|w@Wux#gzm4gb3bbn|KbAcR12P|@1B2J;vlnte|zoJH&t1kKUqtw z&rZF%%`NMR@x;#f%Nn+c?}8rZxJAv`_^B)5Y50*gmD}%gg?m#3V?tNnG7DY(PpE1C z+X(G2{V>B@s}q{G+Z=Y24f=G~w6w6>S;xfSsB)aWYfQ#X?kv`Cs@TI|LN88 z+K`5p+u5A&mqszKm)+v5Aki`N%$?2KWi=S5#|9k{Q1eOp)qi5st%H|!vl+XUavz** z-Fr}}Y@T-5D)aT-T3zeR1mS4P}w@qC^X~T~-j?!PRi*^Jl zOBRRQpS0iq{A*gtz2hzEch77qI^=L@x2NgDmq!*o{<$x`sOxo8{jHrplO2v*H>#I3 zOZcCzS*Nv3+3A8?ezW-B=RP0OzILYQrNpV&z2V*>XuoaG>rAG(&$F`o@Ad@O&HvJ@ zSQc|BzWkEgn&@@R3U+%onb_X{>-B%i?S1(gY7fpZO({A#Gw^k6&YQ}vkk*A8*mA$f z2k3G5N*`Oxs+KDnG5M0u>YZEnUpXGkbo_+IBN6Yp`q@+b6kOC5{&VeBcyVpT<#NY@ z6>FDYOR1Ne>wcu-Vd_7}3GcR+e*DtBYoB@0wDqej71dSW-wyvifB&LPb(V`&%ggvm zyAqdeOb=~Zv#F)YIYCcYE}zH9rtxVoThsA)-ZZ0wmp|XR|E&MTH=&fd9OWc12hfQkW&`c2MIKNxcfA(ZM zhre(9>a3Jg=LzWkJ*8-0rypZBzbH5+koQ&6+iBAR>c7dpuCRF(Rl8{)^Iosuu%L?{ z%9qvd{OR-PRrcG^1m?qA?uRmcUVP?G*e1p+IX9MVK3-MK!cmvz9T%0|Uv@PjsW57S zY(S}LX}8($rn?j6^!%jTgunk*W>aQMO=D+$BYmQ=LsT>FsnCCE=-QmLnLjlk4`wU%64U~?&Dn4?`Q?X)WOv0ug zb~A2XxBuz*dcg|mbeWg+m$g=&-E~UO?P=xIhn*XPC(f4O_pb1ZDtVy!rStTffGk#v z1E%sdJJJud24wcHGu@jkRCXywt!c}H_fOW(xirJB%4FYv#fzdpHz^H~$WwiJL|l6BZB>I8iaOhCn7lr($y1iMxiNFajLhwN%nNhu^A}$aW8!@f zc~&O%9CwHokCVqXHy)P9wsjdt|IdH=?$?`7S_KA=0*nr?Q9LVqaVqb%poL;*z3a;- zt_k1$Xy4(v-x5-|_g?ZjTpG^uyL4bDolh^F z!I!g0K=!GxyMq0`$x%IWzUJrT7Go>W=Lb2Y~E7hH+<=@&? zafr1SY!YsdwliRQ+kDha>7BJtvHX)o-XEnOinzZ&U=VlKdUNx7J@Hw$MGc(&*4#2Y zSsxvLOv!rZ(RW=CL(n2*YZu?yF^{5Jp6y|YU+01S=#ee!9x!~|B&+rFmf)d5`x1q$dH9+}NR65g@ z&?mK9Zk`BV)9qq=hhg2kL+PPMcWjjqmirgHPSo{P&_}o{L`@N-kD@*|mMat{3nBnhR9eocD_> zIa?C#c`ZH9f9u8focG-8mDMGmZq_$1zL{q)#{X2QMB-s=(K3DUh35+etDY^eHTJ%z zAe5ectc*h~W!;YGx%*U#4@VT(dboeH|6-8Wa^K*I>hh^~p3d4*bMct+B_~7959Wnl z>syxg_wKB--5@uGXV*!kwgW~sQ(hh2cJA29HyKrb1+P}L?wSzSa%XSU-PN%YY&+Fd zR`xvEzqTOwZpez#qdPc#J}yys9605T9*c5RIdf!_NO;s5)3&l4mPJYXeBLMh(fFcV zB;uW&mi=mTX>vrh%0HI>i^W&7Z~U>uUtx6!&qWotsfyOq1-c3*uXg*f%ukM|zPo6D zxz9uuF`k|5Kf=!of7x@O?fFWry%FcO+F#R@x){{HK#kEoU;T@ppjwZU!^1oKRhLT} zCmsyDIoAMP=q z*1CvA_Okn@Z`+TBUHJKL-R{V**?TujRB7`rlb3J<{){R!;Y=f4}CCYGdiy@YVfu)t~KW65Z?Z zhAqn7IsZfL{dbFwzlmj(&waLS{n6EIYq}H*ruIG99?TWG+r2ipL?n{sNr%?L#aB)y zbueu=_c}PAo24|_yVbUmJGxMuE%VkUy~^7Lzb7n|VtVmJ@WoS2pZQnbUyC_gdM2&! z$MJkY7|sfbH0cpOox;}q?)Mem>F z>>KL0?60iakUeFy$gZWPw}KT|MW%k&)qk~3>7?fFweHqoi>|A0Huc$Ye%246;?0Hi z^G?KCtbIEDi&0s>_ojN~n=#i<&s}-<`RBUc`x|tw^ter1e&Vs;syFqgWBKDa!rsOm zN!7{PAru$edAV{X@3y^rzinUj;K-N6D^(#=4O@35Hu&EZQ;u6c4PDMVD9v%>HGs(qI}9(^DqF?ZICQ>?$@cRpx7s(Wwun@dJ5;<8Tu z>pILg?pJu%dOItJ=WGf4uNR8ECNX@14^`hAp66NhL3a9AWi8F)2Q=a?P7xLPb4Ks_ z^gjL1e=8qt?N}K#$9(#)XPz6sIUKz>xvTzrtU0HG&a#NT&izb*3)^hW8w_=y9_pDP zaPZr%mwS^}KGD9uAhgBlp2Ee31JU8lCfAm&n)pFu;+!qYN4~u^^>_AFS+RJMTIl7v zwV~Q^z7gkdxMn6DSXF)9-a8{h)l2I1lDColTAMqB4cYAf-I3->^m_g0UeALQXEW{y z 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

(pS9V#bd$ex))HHe z)u-zp8qU3RuBj&L%dKVYZVjuKrEC6~5HEiC+2?PoBY0vDIs9BOSC~KY&7aoAx78eG ze4G2{g`K;5(;>zC@%raB^zYuc;_&&x3;k_fXidM{in{2E(;$*k65n^sv+Z&wj_nhwGMJ z&rdq+nY5^w*G^yJ;Jz0Q!haHC%hn!fy7Dx7|2p@6%k$^78~vv`%;j;Y{JthSeah<} z>otx?ayphiJecj%%Gq;iefKZ*pSF@2TH7|R7Mb;`$XPC9XMeF|Y+Jli?4FN5>=|{E z9&Q5VYvM4|oa>yePL_xLo66E2BOxlTJ74*g`?{qu~qwrj1FO9zki-YJq1OM;)gJ#}FXgE{YonG0*ug0eP- zy}7hW>XOg4Q+XFl=X$6l?anPbZXTX|K8Dw&?AnPMspa=P6Xw3%HD~_Zb@rPgHmFv6 zUAS{^@|u1>-_2r?c|Fc-H%;^14 zd~sn=<7`ofb8MT6E@~UUEf0GqPM*Zn0bJ)!auFJFZf>xnb3jJ3VvC!e0(9eYVL zR^BhMBSqFq`rSsOLr;@z{Ia@jEW1@pS2eXIrYv0>EIn~`(G;7;Ao0UBTGwwLaQdXO zjmi7wF9q=@`R%qF4$DZiP5d~oghBi6q3fl0%c3uFvhMcrSjSbm>v!>7vh~`` z4YI0-vjo$!y_Z=|f4SW!Il*-L=Rl3iw&s%?HX7eM`PFx-WZ9Zu#j(aKr9+q5o&GXs zW!3H6db2jAxv%{`*#@)CdYR7o`rC7(e>*p*2Q%ax`{f5*1$g|x4m5l$@=uLuLGadTp z{ym>%GwHRKr%+p>5A%d4Khu_ezG=8FEi3v}-PF~5iA$qXF9pB3VthO5%$4USclF5D zCLH^hve04J5+o`17d7pyhA7~+`Ve)9xNjWK7n_Q4sR7dLK_h>Uc4!{oO6vr+8cH4TMk zZF-YGP2ZeFgoN}zpA&Bd9SqpF>8RiA&4z!bU5oGLHN88>)AT|FXNk4W zlDWRBlM|J1%AQ;m`?G19&+I98U$+Qw1TP6cARxJK_R5U&R@>ErZXDCmTm5p)t!Zl( z&zx5{=X9i`wS)29S!cKIe|{=0Y9m|O-5HxCGd45Mi;48`J}_77esMwmmRroh_1@P_AU$h8#(z}svd*MWxL7z+%s}~wq&<#*nNKK~GMk>?LOyj5;Id1f6?pG`Z|~z`nfcpI@$;`TFZ;)}Xb=uANKY?Y6+@lj8jJNX8wJ z#Xd{y7iT}0y?O5CQ|4!Hnl9xO-S^wOd9V5H_hmQc#eA`|cJtot81*d6XH(JtGig)K zPknjz`3+Yq+e3X5wd0*j%<|2ws~dC~mcRa`!=^XA@7%HvYP-{xP22RWd&k>nr$6jc zImXWZ!PV67?N8HoE9OW^0Y#Qn-t3zjx6XSmSJQAVA#MAPlCX(2X0v_P$^G0QQ`XWN z+c1+iB;u;Jbi>BSk7lf{c3S5ZZPx9-uj_D(sJixd@7+vlw+DxOR zbJe&v-8EarwBw55iPF2NzwSQ%DA4Pcell|U>DJ6yM;;fRwoIR;)|QxJc#0z?Xo9b< z>ztg|Nd^y=u2`Y5`s*O%NGRm(On=n(3k zoMGZ)AaPP^wOa6owoEs}r+Y4JVVZYF$7}OVFVC{T`#V^sn|WP7py75YQn}GVXi~1^ zOkRabt?3tHR4pnuaoZmLGlyR}dtZ9NCdr9!P8^9jw<>aHz_Q!la}A|dzUx+E_E2us z^^Wt_e17(l(H+Z%RVANJytCZzlh;=Eyz}nAv#k?PUKLgrj-IZ)F+u#nbEc5boo8mQ z&zqoaaH=F%Pw(E&S7|%nY`y8QTE$bNt7+A$BS{-0&+BSwDM|30yEHfWp5nxUg(g=u zKP=0P64O0;^62%uE~Q_1{P)zD@SnYI`1+sf>1e~l=|7ME|LlAwRl4GTZ}@|-6H(Jw z9(&=mY{3EEv^f=bZn2t#pRTZLe^i`W^(<@exzdAAn2X*tT&|gUHs`>#Rqx;2n|wAa zOI;~_S>2wWeb$+|5iJu`Qd}Kxv{X1b-d%x1}t!ZC9Ca?4#51dbg!$$ER; zldiSdfh~-adY-+0v~l_Of|u3#N6Kr|&+jcfC6wVS+J2mYfoa~^P2B4j8U8Rk%>377 z3s2y@O><6eDq=qSb&rC>&rQ60zCV+-P=5U5^{a@D4~727=70Ke+WlhhoAdx%)$SWr zKd;J2zg%+s>X}~i*hY7ugd-NEDe}9&$s7~EcxjDbfkkY^UO%OU28DMWN_TzOG1ui# zV##5j(>YI*7H&5y@)QZbQhc?~)aLK%#6@YE+v^@=`Ms-ZWLE!uX$|MhM_sOOc4V3Q z+gcskp>LwDrZo4V+GM9$HGWDzYx&xleJ>l$OWz`0aO!PY@yDa$#s&rlPEJ<8Xu=yg zZRMIZDQ|CW{qpr|;j=R{CEwYtbU1I&Bf0;4*~C^Q_l~vROlx%HA5M{U>i=nI%jY9< zU|#!y5^KYWE;3IvruHS?+wS@BcPwTpMSk${_$8W&vnw|O`Dt^CCV?Hk!h^@X{ ze!oll{U4P96V!Hjq{ecu^$on$w{3CvpKp6(ZfuO1Z+X4eQd;Ar>4%ODO<$F)Pn=B4 z*ktrA#W*j8Y0Ax8Hq#xHc5W&UdptS&%88g8t9G)~ZamEOw7O6C?)S2$IjOJtwa+i{ zc|5;&=eaVGRJ$O*CtjPLJYIU^#*Gut&d#~QW-vWU0vNZ@%!gZkE`mO zI8ku*#u;2mN~GNXFiFZ4QWk{+WlwFYn#(Eo+aL0mAWIeGb3R} z@Y}m0S4=kVa9a2}M}6@=gRQ5-f>*YEbiI1yui(sUdG`N2=3GkR*V}$-)!OI_XDoKd zRY={xpfG9ilw-Su9vyP@T*z+wX!+*PGLIWM=5-xilezM^BDYJW;h`&?ZA>g%oo3CR z9u)V&sr$#vH*ZpGG$MB9iTVXQ7gm3qoBjCB2K$Zm9zv6L_k?Os3wja6*xYEG%i|U@ zD_Xoc@zKYM2`+Q?t>dd|S2o$YE#Q&C!N`{5nu0SW9=urjZszlk&js>o*L^>uemdo7 z&>7R3igi5KYuqGCcHdnSzrXI9)0Q0+YX8f^G)uQp$&)Y2Ea&m2FmwBg2a-vJyq={GLY4Pyd~UEy(co}04InWK)B+B&X1ddpZfIa+D9c&lcHfI@;)=Gs87|6+r!x+gIizkY-hcDZ0qw4)MH-jG4%I|# zU-`VvNzreP#lcrsS9cywlCiIw)6~Qiwl>ODMQGvT#mxKf&;MxImMFm2Zp>uEsZr*7 zREwRl1p};b9HxgvX3#u`0WA+~)F z?RK#rH*`&kyP^|${CEEDIR}&VKmR(&_or~`v9>6gNeUK*KKcI*HhO+h<>cj*^vq~E zoOogJjAbo?-2&Gau3Ol6iAh}Wzrpfqrz2Y|(rnt&c12u?Xf;r=kyB5+Z;-y5ZAMe~ zq6-Heez_13@7fqFz+)M?aS`KG#w`&%?vAXzrb|!E@ZtG-(b}f*&4+;N7d$$zdpdTC zU*-_tYoF+~Ix;4_wdq_yz5Lr ztrcsQ-gtZT@v8L4yQcm)rnF|q1EY0!Bi!TH&wq7GDX#v{@sf_Lyqf=8=iL6R(*IWO z`8WPMj$8hk-plC^e)8!-p>ERQTMX&#hjp~Hj|FSo*pe!|X?suGF0F5Ne{}hdN9}z4 zH(Wu|YGJ3r(y4M~cAvQ8ZrPvdEw5?Vdew;eu%p&%>5099J`WS0w!OVm_qUa2&bwt< zFO&TC{*yTW=GEgiYkQxyGD(Ntr+-hjE#dJ^;F=(l8nf%MTi%`=-DF$Y7T(TnAMKj{ zapmoNtt=v`*yjFs%Jr)k%b$eGRTi0x$JPo*OL2W@P2y;8cd|U={JnlYvuyITCWH9y z12LbEJ)K;2@YGWs`CZlPO3#|^ZINxfdh6DyYipyI?|=R7-LvQR|0}O$G_TA~zAwGo zz-O|nw)uq%cMcphk4ufeZOI~ZZc>z4{JzekQ(KQTEtavWVA#KS;#=wI7p|5~P+tCf zWzN0^-L;}$=DbWeyQ@?uv!L*@Z`0-DeF_3E8s+BIKFeHWD67I5s(Z}*p}Nc^gVxEW z(c1!^_bskowNfMGBk!DNPi>DIOmUjF{_cTWsiqu0UfMPSeqT}@?{aO+kL-;W^!c*& z9J^m)>gV{BMRgyY@-`2OTObtdrCD^E zW1_|X6qjQapSOxjl;x+sRX11EW?gegU?`&v;Ma0^Znf4X>PB zj-{<_&tAV*Z2N87$G;CAbo}=2?(D#{rQ1$E|Gc!c`0SRtwLK=exw$7co%!_ibm7jJ zDbuD2^&h{vzux}wv7vyj4v=(N%UB3y=S*>XNIQ#{)fp1Azf=MHlJGevTjk z|0|hg@?I+~<8))Il3;u?$t`c!uPCmqipL(aUdf3#x|!eJ)8C*;Pcb?=F`dMvT z{Em))6Air0*Sgj}Ykj%d@7$%-I~AXw`h58&G>L1)r&l(=Uo_8=?e*PuSY=(N#!=Id z>C=Q)XDq!VsrtY;pi8{)=r&%FqwW&d_vS?GpCc~!pLfwir?Q;fv<3MctJ;i?MA+}p zzOmsem(*P0o>`(>u1w$b`D^Wu#m{tH&uUG|H_NWjdoyF|?rE~&XLA_cH!+G@>&%SZ zFysC6l2T9ck~3YACzsE=xo)nvi=XwWx~u^E)n?DQp1iq}%-Z#K9`hNI7uwPFQHGPt zVg){5zKFaNAXK&$h zcxm~EkKS1y!me$qy3BUxVB9^s(n(WYOV>ng>DsYtx@T zO1ib%$LH0~&&=Bc7V=-VRoe09*6j|SJBJevD(UThR<&nWzjFTm-rKPbr$2=qJ167L z_gW`2@?6D|>B+KR?|fW%JM)X1McJO|sjs(hT(Yob{=XNVuVzgvzB*OfU=d?m+uFAFnoh22%(9DimyTc4zV9rVxa<74;B8Afv(`I) zzqvQ2=Iz&*ecR?Jv-@A#u%qvi6Z;_(L*K?VVjGgKs%_JabS|iw@b8{sSX?#h*(9MQ z*UUD4y~LeqU%|sHs^}0JnsV9UIAieqR-f9-X?c6!aw$FUyDX~l?9}YA;3bE+ckhm@ z|Cp+yEx_}we}PE&rXo+y<^BI=2rBz>B!t^;ul-;abt=S9&bIBL)`3Qahi|7%*tu%+ zjMM9Gor}JhxXUf(&cDX!Oub;s$}cQ!mz#w)*jEqeXd zJXrUbrTLQLk5|owrC&asv!$)etMl;g`1xD!Sy@~Eyt3TRG}*T1`|kU5MLAT0>nvAq z`1aG~&(+eo!s>nx3M?Y_R+-LP_VG^f`Ljv)j4I7$ESp)#+&fdM>(P;irUw-LcfD(M zlysXRwCmkgQPqkzqjj%5J_&3}X1c;6tah4d`9fnWE1w%B4|M}{zh9c!vu42p2h|I* zszSzso1Ff3@m^W|_=n9}lMoKMpAUIOFX@$GQ*yF}bD+;ei^WPU3h!P&d^=C?*dx6X#z{Q)9yzs$E#1Dly|Yt5 zbzi`vsz|p&D~%O7kGkHbdTjE$KhrR&khw>~nfYxAZ@-`VPZ1}D)m(h8X$33VFMjO& ztXJ07Darp(`dxBK3Cs5t@{zeNVInFl4?oJewY5!H9D3xDmELykWRIZL%}YMB&fCN| zJ?75-BFpz_+jUn~9@up8Y;ocF(_j8wIlQ25|NP(YcJs$xuY9qvec9cEpK7OPsx>kB zw3>Xs7Ph(QZq^b9d%L8bp0>=WI~|j^|M<9F{y}m4zgoNBKYd^PE8F+)>hTwsQ_gLh zpXj=t8JG_CjQsfH?+CbuA}ZZe|B3Z4-1=r(fR9j4rfE( zKULnow>`DDwd1U~;#avR;r(_89gduQ(7x{gmtx@Ne@;=Wywvo%u??HL~pPmvNma>hR$}`F_SpPKRB$UkG}a@?8J_-1z;rUar4&Ykr>V zj@VyhuIOOq_T%0CKiV6YiQf79(SO5^Q-|MOR$FFSocFW6+M?={#OtUSn|}}VXKJi? z{VZKqrWz3Oaet1{Pg+qzA`emLhde*z=$DPS@Udb#@t!0d! zZT{iW`uPiz4UYBk-)p(`-)w)?8_i!$T#NhuADsF+yzs#j4lOm=_Og$U+2RX)L-K(5V3a7QsnyOix+VS;p`2(|GKTn$1`?$L-%ewn?%av&tt2gyNY&d0f@l4lL z?}=R79?01mIWP0S`ufJkO z;Q!O6P7MqXceju^_Oj&CojYe99&S&c+v>MmL8`5B)vC;?^1V)S_buC0LO0eeZCb_h zvE8d9qx(a4@(ich2UTtbo_V~i`QZzp5W(d;3PfDZUP!Kbw7j49vhlNpdrq0&eLs^S z|5Nps9e(-!^S^Gr8ZzDTCGUYpq0td?`Hw3OFurJ6ENBwWb6CJa=K1ZF(zjH)S2wb3 zQsQt;K4LPn;?9gc*NzzYq)hCPxl#QmbY8_);gdT%tl#YsZ0XeTW~osw**gDW$ZS9V z>HW{V95{TO6EY0{2s1iG89r0Vn8)RpHiJo-fq`kUjpO&5dU`kNEP0pp$J^gI_9|Pe z&?jx_=rmg7q(BRsc*37`5z~JfP7;@n9 zT%|KC8k3*QylB|!X(8fTS{ZTalGAp%gxGA`O)3`_3oe?dA#CgZ^If@oqK-~r&;5X%2H{tqJrA|tjut$!zPYxA1d@0clpRFC>pR@q|A&6IedXvMdeOc(*c+HB{#KnbQYRO zJUQ~PwxoDKAgdE;CTS>5yurxIWJ- zW21%J9fuiQ%f#G;I(N-MZ^1Y!YzZ|Ejkyb_?T|_@ukXl+U6uLhOQ%3V!_vs zKfXMBVrEy%i-HQx01+iy<(9pzGZrcwd$Q+?*t7sKuEJM07}>1c3)XvI(Vo1i;?WUK zxtb4-$BrFK+o73e)az{h%9mf7jgA>l+u# zHk(YVPB^gO^OM3b1_q`jdhv()R_mwE;OdfP{5D5w?!Ejo2RMWcn{TORXIPs#mHW4N zZ;y95I^o=;Ds}hx7wW52pZ))mrak4zOvkH7T$JRlThu<0@Yc_A2~`veEwFs*X{lh) zx?sVkHg3J0Eo`d_+>gI}A#HEZ-{LUIr)u|ZO}p#vk#9ui&N?Tx;CG4i(^l!7k5;Ya znf-K%Mf09JW=%?8Hz%L<+Lo)Ic5{~6qvm$WS8tas&hA($8t2FB+ptE-^U$S&37P9p zOmWh<{#QA+<*Co9ZF6PHS0*TmPnh(p&RS4#Go#e%t#i*Pq!|k=Km9j#`peD2rN)yD z@A%DoxRXtG<0->AYk6;$bUbN2H*H143uVcX9dt8|ODY<|Cl zVV>mY;#b?BeE0d9nl)itrp%-(@y{D4Z|$?MjE|C>_@zEHG;(JW>uj^!M`valzqz+} zwzuBS7G3e&gC@Ryb1WvVeSdC#qp^Ct#Z#}DJDV79o#!pO`0ebS%Fh=5@9&&XKL7sN z_q?5x|3~hg*-;>9_f;w1b$ap1U0iXMAL738TK@R+|BrKC-F?%Z|Bp0p?PlAV@muZP zp2|7tad$ceg5S+%D^%XdIonO9_>$~N174rxORmQZB(45gskfVLtUNBOb9>c7t)m`2 zf^sh(EuFjmQo;4oKmGP=Qgw6^d1Rj-Oz-p4cRFm~p!a0jZu>(=7C!%Zk=eTP(bF`$ zpZ8Y(jL6hB^j!GX+&(>gzeCZ~jc-p$ugJLLllIi4Ipk>DGK%9Qt7G zAz7>Ao7eA|D|x_|w`SM=OgELAT@y|UDV*!i`So1I|A@)^$wq-kG~dtrYPWiq>fYj4 z=9+i^hJD?}uuQ4h^vJ1ClTCBBw6?0sZl2(G(R%+(zhxX|K0KFI#5f+!{~-ANm*s}n zmFIe;LPRV%+*!r%S1@ODAG^7A_1w_xvVyPI9OWv%va}^G5DDG9W>rgY?Lp6jioqcv zEsN9^X?A%gXsAuCRa-B3a>0R)$KTsmMC_h2RePGSUc{kW%Y^>q&t_p~<9JFco$6%TY4A6A~hXTCQ3+GVrC zKGD_F8aoUv3>uezDx21`!LxH-?gxh7rw5o6SuW-nj`1QSeFIMZ4X{y zU|?G6%2x64>*SoBN!IW8dp_Q{JU$^MW5Ncx^rRKd)92eaywg~CV`1=pkwp;(r*-Xi z%2<_X`3+>RKl0wmLz3^Azcm%|Uy(wt6HNY?<*qKI?JG`pK6* zeSV;OxpM6n1{Z@1U(NjO~^*#CGXk#TU4aJev$oF zL%uhay&o3zA6$36(lOrIIh6D0I|k)I`}Dr|i^HXzCVO2tl(W^GMxH`Y@()IgCf1Ha~c0I=NLhJXv8;2dj)twh7PyQj$S-D({;V z)PJb)dYRA{eu0nQH~!u#J|iR2%{5c--@}hDW$MEcv}Z4Ovuit$b5Ej}cji3*4HHV* z7RKC56+iIw^}3mSZz2qx!tO_|mE8UF?KA867%PU<<7+SbtzxkDSt2`4Uw-@PEnm+p z*{^CG5}Z5p%GF7dizL4;cmU~y($?Cu>;E_vVBmMhK7%zQae!?<&0ra^`jn-7!4YoW)z>h*_iCa;|` zTbPHJzv$OdcL}>~lU=)~3rNZ)RBV{Opk`YA&EG1G4h;n%kE8$p2o(`jfAHP-%M z7T26wUnXbh9D1<$`=)rd`FRIcn*W%--Txdd^Z0Ll-=V}K0b2$!`%Gk`*)@3(-oBt|9Q4D{l)jAl|N6iTUft2 zE?>0xMAJXv-9MgAc3<(~*vpr%muG9(ByT#GeyTCV>-suXLs5rw4BC-vI5XEque{bN za^P6a)_A{$iIUvLovl8<=YJ| z>Nkhf>>m%@?M{96x2dtqom^?>!Mte(+k@Z*g|{3M)y}Os!p!I=f9K?bSJpcpZsQl8 zt{`_&V8)N#-#$HFF7@+C_5I`GVR`NvdVc?&+1>keKE=38JA3D=U#}~3YbHEqcGRmp z-^=r^t}8w6=HcY^+X{}0zJGi`K*os$0i z514G(f81O@{lm%G`p@4T6>nhDzw_I-YO>i`&1u0Ljtjmk*w=3B^xylv=w03(29Zwj zx)T1qY910LbMKw+EVG~g@6GQW4^J`h+i&h>pBHuH{oNwr`PqAUf(r|tJ)QsQ(rx|V zkeHOrt6L}68wAfgkuy0mV*T%A5D+tU%&?{!m@7*Z0z{`^HXEsd1be|L>KEG9&xar=}}b%@SRcnw0Nj z>~npk@|U@}hZkzSDD3^A^5IpUwa@#Rk56=DUZ3^3y5-zV<=-zuM12k)5HYw?%@?Xx zC}5Y#!;{-I+5Ox6`u)!yAGz54Jo099wZ&46gjbU*?;o3>(s`(AW<^2M;_CRN)+Vay z=dQpwF=H-ny6HWv%B(_!}1X{OdDIVfnSBZ=vs(&(~%dR>@NN4() z!}%l4Z_bnQIqT2!%&p&)dzDxE=cVcQ&TqE=tzY)e*7RF6ThXE%ct=j(h)I!0DUi4SdUuP%_h}a+78%{K?^<^J zLSTW_l_yi1<+zpS$c1qF==LnEC^*3>rXghdp+ctffqs(`{c2|hk#MiylB2eYRBPkE9Ra(kEjfW#0d}B3hZJ9ZY z3)_xe+4}jbDQ}XY?A73tyS|<-&@Q@EbwN_{)uQF)Q#PbMDz#+ja8uS;#oWG1px<@k zTsaZVgBos+h2*x+O4!x4dPOm(n|s@bcHcd5>KqIVOv{@iOq}k_=&^h8?NLCg09)T8 zuRVNoA3ikX2|n~TWTI-vYPnUXxjFiKgpGMi+S^xcI+E_o@ny$?HLIAmUtY2~TVnm~ zMwS;F1)RP<3Q%bgR2P}LB6?4cYVXq(p4mRvn@Z-rRukx1q!kbtdC=v*#w@Mom5X1q zbzN>{I55TFZC=E5Z*mIQSY@y^gMfOqYrm>7GJr3{c(v^`rOb{OH5uD^17Cu zIZ-%W*T8jGO?hxaaNv~4(rrvTZ;BZ2b~K-Kf1>7%p1XD1x!9CWYN;M|ZK-*Dq}9}V zW|f~#=*^8>9FsgZ&Xro8^L>eQy>;!Zyg!#&-=3UiZCH6WLi0gbUir*_^E3OsuIg^m z{5|tPf?0w=={-a7ZHCuR^n|TDGxI>I-SdN&BqKMuN}XkSwW)DK%niljTe6m!HkT`X zeXAb%?EE*;+2vHs4DH>Ov&uCEMVWy8=Jni-u>Kg^W25B$wyc24Bx!N zy}Mn$?#E#Vc7f^dc0A@2|rNR=@rG*`x)g*KLZ5=e{pH6drx< zKhL|R#V@~?^sJexT2QtrA+s%ir$=GyjDtbTBut)M3jK4?ecjR3UYG42bfpwLI?!$N z_teMC>D?)-W3`yAl7*9()&GvUD_4{lW7IeM&61x@t9O3*VTxvF`eH z>~qxhm0TOIO3r< zSGm;z|8_F0%gIU5dlR#5-$^l_)OC5&%kIXfZ;TDTuJYaW)Vx{!d~^7vv(%^0lx5Ss zJ}0Bh!FS)T{dfPJcoIA5^xu~emey{qniJAg@9Vr$m8<=7QIlc0_x8JGvpZarL_|ak zu1`9>;7QTjnoa6u5we#}Ca9!N)6?}4R`fg}xn|DINq^3^ADX#(_j&8cO{{z;(}lMi z|J$kZ`&{b1l;CU655+xGs(7=<_9JAJUPEK_SMddCJIHb!jC>Y^15tZdH6Jy0}4W&=Q<8#wjVsle&Q*Y z#3okFQ>-PatHPH#2<Sk+qb=aeb4eRn8!OD%Zt6#n{L;3s)jeI?3j7@hiTqF z{?^<|nrcy}$7XE3$zb(Ct^UgVPzDC3729(d{oXXp_tEQl$q>3uK|Nj|we*>`^orA> z1!q_TZsdALiS^yoYg^fNAt%Aqw6D?QX7Q$twlja7)w?`dTVoq{$|ly?8>RSn|2iJS z7^C-mM{(l2qPN?3&Jp*&%=hufw|*#<1$5Wg(6;ueqshNM0JU>~?(6 z^~iNR(aW;m&fz}IT5zlL)C}(1iL6P*eoW`y7$+So3D_X=_}-G!k9yM67z)B_lT^df6W{KT}-ctb2mq>axg}J!K_ZOuh=O(m8E0*U!t_ zyEu*gQ=-Vdm(|a;kKc0oEq=)QK@|m!$Q-RQ z-9I|f%Z*q0#it+Uy?f4fW#ErXtW77v(>Sb4y?IYfjd}j_T6WI4nR}i+ zmPv8bdp$|!onY}?v@Llw#LzU zJ9~_jeOH^&h)GXR<81 z_`;fXZ|Cd62_iD9K1E-wP&PaG!KG!@EUPIdGi-!poGrXQ?7DJ)79+PWkD=JKmFw3Z z$wP1`bzB0-~NgysIYQYkTa$ z0gii{xV*UT6lcYo7#z9~(Q@jR*RkKf3a4EU2o2hxP$_oG>10q!-eUh-g=>tJ9VMXl-5lFb?T=cJWvo87T$3;@6ksK zCk_!;$Iz>i^{SqS40vMn#Ahw@y{pG~MsnqhwsS8MKwI>(CYwKuIiE+HqAa7Nte z1m7vG>=kQu{^ggy{ZMXy_T6IHn9|Sxm!^cBF1>aCk9k{GUBB$>*})6tkJs1A$N#>k z&%nU6^5xf~=j-3b9ru^}#n$WkjsIfyMTWh1|Ay%0EjzK4p{a4(^q~3%a_1a@ z*V|%`PXB*BJVU3j;Dx#UgX!&BKX$LLo0b&4SoOvI&s_X(UOj1^|C2>mbly+)Ll*=0 z{a;)EXyNj>^q0N$hnee(mCx-wt8`25m%dz&Zj$SD{hjZ78$a87%597N&AIQ>QvRSN zx9aa@yticXGVIRQ@^JZf-SWeY`=7<{-}LnH7q}?@_tX8)A75`5lz#ib{@+{sn>D|e z?|eDw>Wqtqbsy%|Kb!8q=hP(We_iwIzNSgPy==Mnx2E0ysreUoyi42n>$-gE`Sbr~ zzTb20^xFC_p?1Z0+3tL5x)7zotr{FC!WuboVydKTXn<_zove)!I*j*X{O0gIPYJ3v zto;@`E%i>`cPDl|P&A31a{4(}<6?%$VFL|a-J=FPNgE|LM({*V3k)s2m9SESYu2)* zr8nnDHwX*fx_wT_l*eZ)$6=o*W!)@)dwwP9WJR?}N-e3c>6tW1X;0rx(GS1>?)i2r zJJb9@fX0!t=J)5Qd9*6XaW9b6VvWmxBps|Q!uR;2Sn@Gu7bW2thZ>h}kecqSCN|Sy z-Hmgpx7W{RY-zdB*>?QGqq?TXU>C0~C97Dy^>@y#kErFfZI6Gp?|((l?)|^~O{R(l z1uqclZcExi20=`qLQBUen_+S(=fUxb8(2gki~eIfNQLMBv<=NnJM@|Ib% zxbE;t>b^-&(Q$C~mDM|*vQ8y9y{3ZWa-@rEq~NOUZT7$7{~u7d|DklfPSuEc#_Np+ z&d$y(i-bZ=uTBxI7TUQwN${9kJBOs77Z#LT`rXHQyJaU$YKJEV3^#AidZi5o${6b3!L#HZ6`TvLJ2ZqM> z>NLJt`;0sOpVa&x2fSl`i$9cnYs}kwabe;yrb4Y%t5<4#RO;c_E&p5n-!FINKVP@M zOHcOJ&70mFz3+#w-mYBx`+sh)|F|`H{^Qg0cTZAUzDZ%H*eNH^U=>fNSv_G{Qfd=D zS_&+B4nLgnPxq(K9j8bQNU`y0cZ7)R!MA0>5fL4SA37*>v?#YYEtHf~56+1Z`aO-o zvB63`%BN`Kj-9O)8BOmVuGGj8T6MV5`O?e}z6$OP3{0z(E4Z}^R?TD=0BlxZ>&R{L8$m>vUvHOrJ@de`KK{ zulMv#Th4ge7#;K8|4Y)o@)yHn#vLzg!$1Dyk3XAi|Htm_C$@cmUgqxk^PvA_*_wyb zyt6C*Ts&T}`maW<{XfR5tXkLWA3Ww@*>t(}^y8%q4m7_iSSavh>hZc$^ENY2iLDT? zuX*kklCb2p!T*2#_Dc(9w*US8?Qv9<>i<96;};o}w9UU?Z|`n>TjJ#_wTO>$Dm;CA z{s`RvcQWqRapo)A*FAjy@0ow0|C~pS@wR7o$ouWxHd!#=`2X+te|_H3rz}3+I{)*M zz5VI?{~pwB)AMH8*2&KP<5~E=0}-$1);#tue;ASyqi4SBIJ448*6SP}-~7G*@Z@&C z3)Tu5QM=pL|M@AdA?|GR_k;5ryP^q-i@T<6%Ch@+)PAu^#fbcEgX{`Bj`Qz5df_FflXCis?3iPr*JEaGh^XNDu)~%^#U_va;Ka#) z9@*C&Ff7)b|L@A(oT#vw9&EOE_Z3_^7})%H{l7{1_x8{JS7`rr?dqSi_x};Tv$*}o z$zt~(Pp1DfzkN+7O>6r0S4Ee1R7uzWXixt0^!vQD`&U=*$jY_lUiI85Qe$R!-isdo zeq$@EuFP2)T}{UyFWj+XM%O7WnN`iLu3I4WJ@?b{ttU3w{N)$A7{`0qAv823bgtcR z+o|S$*S|`>;C4v!b1X@T(K~)-gil4<{0`p(sEjxsyml6)Bdk-z3v}N^6~de*H$;RO_RP+b1?jB@Z#OIIeVTcdD#d(>}V6a-s!T~Md>0-MX<`beP3<9*FBg1b9#T> zba}fS^EFs=_P>1`volq*y>H(7VjG)d56$CU*55m0U-S3AhQ&vfw|@`Y{JAXu;nPfp z`VZ;%pZV9n=Z}bct0ed8arXZ|xlv^`P4acmPw(KjIb`h4Cg9d$tH1Zm?OMHmU*!LH zeUDK{_Va5wwe+mlT_ILcx2V(sCc0YM8ZW6syn5t|4 zv)leDcl3$DK%+^lpPA{X;>OSF_aDsue&=xfzrXb#udPhv z(wbIy{P=se!)ISa)GVuY@{7`JkbLz#`+o`l>2<#(?0=k_A6)RGaGvFz!x8D~OP^-% zNcj3G^TV_|p1j%D1LMLR>i_?!cfYU-)OJem%AED(%a?*jM>x;TwRSHrH4e@^*&i-K-pW2k$m}gSc$% z2k+jUd+=^-+`HYc|CO%4y8OHU)qA1o(BgQ&TW)_?S?du) zIFrSPb!%3bR{xxH$IE)fyIqrK)~0&&>uud0C|y1=KYsh1p!qAR=iiI)-|_WVN3DF! zs`=&1=aucgcR2T$)|78ATjG``?m847eJ`)}cfQO<-n3lT-whnPyY>5xXPt5sT^gaf z`|hn%N^+M1_G{`a)7<%T=Qg$WmNz#Ak1`7wIm~odx4vAeA|-8p$zHPbceM3QhewTn zo8QXW{W361xF7fJ_`R0~Wqlbh?i{_-U$J`H9C@NrY-y-?-al0#0ZM4`Ldyecj|CF4_ zUtlEoYIo(5s@G-a-!11mB}dFyQ*~?NJehmbf1Em0W~qKGTJ+5J(ies=cKrBhy*vA| zOr~Jjd5a&v;!YYE*yo>}mFpE%lq_j#wy4%G;#_Rdx@w~=HjmVLfipjS*W~h6-pbTk zwexCtm~-2g&YdTeh1M!~eE3>xbNgv?DXX3M)%lGOU|BI@&9EhgJf1k#SeS;q&)%a)-78YX!OzaY4_gACld;prXONo zUNh}VflsmXg|ofMKiFnV)_Z6$%=vS)j5Xub0@gdsXD{`qe%jgd?7p(D>pL}V0Sg4rk>mWhF&U1=EPu%zUy$dl)^$VN8{xkZ)K`&?NNfRb54*G0y%s*~% zS`h;S)0%B&d2g++?Y|#lv-j4|Wg@Es{$G3<96Gr`zn4ofDs)flv2}v`W?stNe?M#M z^lu8AHMY1$mrN5D4lGdl^dr<8;F~h<$T#={eac%wb7=|roi44hrP~K@6kD>&(C4*r1yUE^!oXG z&pvfBE)bjWX+nC+uKL4If6An3uIt!4)7SavU+Z4Iy}4c4O}u8=yQi^yUctI*n#=iX z)6`^jH=pU3i#@#WRrNAqVf$;HOAdK;A35pFGHb2P`E|C5#p0>1$DeDzwY+D;T_43+ z$#42;!-jxE9o@!jU;S3;n7erTJ14ojAq|eMz z(7FEZOV-8i7N@G)OQamV6Tkg?@NeBR)rS|d7G4#I`drz*YsZK7Ut8@mmhH3+?UeuS zc&SOPS0K<($)e=MjxBq7mwdecVO8`zxhWI=u=Dfq^yD57tCnlJRJ2d0rqz;fvE;1! zfQF;{72LNrs>+sU-{7%-eRui9w?cl)U#;wwv-&%6s>l7bZlP(<^a_fem%TjIC6Tef za?9f#Zw;)TH%UD4S-@aEz2a-S-N$X*Q7f_yUVL9Ssnf?r&5fIlHB;k2tJ9uz`-|cW zouyw*moa6u*6rQQbnmWs&<%w?1-7fo;=+Btr>*9dL_K}GOGu6T>57>#t(79>vAg~@ z8ko0MTTiqpxh$vgeb2|2(dm7?0^N?O!db0u9xvl<&di_Rm$^E4ovhr(cK-5k{)LhS zdTXlAHn^G1{QbJgOYS&>w)tzB|0^CXGxXTc6YA2JFk|6`1^Iv7_=F}YZs94hwKmsi z+5Se|Yt2tP|M{oqZP!`5IA{8NKmJwoUgb$m-&7Mhd9I?P$YGBZjTxs_tT^}W#;LUY zR0VnAMc$B`R3qzJ^ReA z>$(fCZ+;_m>#Oj(o|m6D+LYJs>-l(e!EB>q{nugd#&tY`<=@Xp zJFETtdhcm#W2sBNYfnPR zJO2Mmr#Ej+kCkuAy}+$G+4!Aw`Q^~|>yO_WJD&FV8xZ}i%=5EGhCKrV)7njO!WGF= zcm!Vk{#w^!?`~3@zn{ss(_-1xr7Yj>Wcg2c`$^#3 zg5teDt-ng{nl{JwM#YKVxX99qy>2Ee8d{oIE_|7r!#j5^_w~kpQ7N(4R!g^Cnr~wI zI4CAvZTG$fby6!A-YAiYS!weBYQEXZ>*fdd-aPMJFX7#i{_S04@~S)R7wXPMOUj66TG6 z)m+?i6&Q=|+>`P&o_EzmqR{9u6+A4;aMsBEbiVc zO+K|e^~bR(rT_kwO*~S3Gf4WHSLLGofEC<(xjx$jO<=t+bGCLBDe~Ua^$i6zw)+n+SIGo zC4AApqFHU?9X5U4+Og(FmS2p=Cj;9Hg=bXa?(?{JZmYjPzrn;fU_IOQsF@G5`7QH* z{i=}Wa{2$(y#I>Yqxb96OBmXI2S&WG=$NoPr0tnFpWW3Q%lP)lOpT|BFPythubr{k zas8UR+~3cKvF>%xSouR}*%UVg#O!dP^cvgysT1FxzrMS& zaQ!C#iHDpDioCqiJW~yF?_AyT%4M_vr-rLvqPWwyYFzoPCx7zLiAVk(+vQIl_$a(X zMXd9rXGZw6H{Ja?_nG$}R5*G{kndDkj|$8q0L&yI68=k*P{G6Pm< z1_k|Eykus8x$Mky3~Ntq%HZ)#c=-4+qy33Mt=}E1SC$DTzYZ0eUUbai;G9mO8!z~e z+^YW~ta-xcs^yF`szFCAzc||}`7M>3mHxx9?aR*~1Hm;*ZfQ8a-~2T-)r2)w%;|vF zQcG1=ZZ6BgZqZJ*l3l2AkOV5~-F1+tovVYL(doC~bUG(IB(XcbSZ~oKR1IaTbTGuyL zCBOUEm*wd%UMoCr-kbjT++FfHAC?%iX=6q!#V?lU9^;}C`e#Ho5!AVM%h+dw+55lAbIjarub52x6kXYTP{2FCwq1McH4o2@FE(Y*7u9&^d9D36 zM{3vmZ4o_IMM=wc{509Q+-aKR4XslVN*WD+I&YigDleF=?-Tj#$FE|So4wOK4`#kT zsgw4|zi$`Y!gnD{5B_mcwWgZ-xqi zrRtBKvM=XWlQ7z{^O48P6F+|kElyQ4vVA7}|6lQ<46*dff8U)fZF^tx)77=}3v0f6 zcXrUhp9^Ex-Jdw&(eZB&H_ujl z6!P5Fb@s^@?T3{!og8(~KVm;K>)Y#^Z@ZFC9Q&iaC0L)=|KF2^naQP%OAY1MpWdpJ zv+Yz>)ud%=4^B9{zG~UtE_!MH)v2wozx-Ri*?7<1d)cd|R#^!xyB$2;GtZ3Exhj1( zd%NPZ9eHcrlBPV}u=cb?v|L}^!KHWQbsyh~IJxs--SW%1UlmQGxs{3^*2v5MtckGC zWO=t|!pTOwB@y*@@G( zFz=J++xRK%^NLQv>HkuWuHMBbl##9c@`?MjPV>wAeNLHt{HCt-_));-@axs9w#4q^ z{+FQX;=0M_&+9wCO;0zd6-}R6vQ%4LTuNB@GRun8+hs9#-krbIo5{Uv+5^AIyCoC8 z?c8@g_4-k{B8Ntoz0W4DFu2;))1|cMuZ*;8s6b-$T#kuq%BN?odk`0B^Xy1Zsp^6F zSq|a`Ppa0dUlH^a{U7op)_{5K8FMSPJm*;~IUG=~ zWtG2j``oXbl_{#i8tyxlJ(zre{Nd1)6=W}^<&-T zrq-A2l1u!>TxDNO-#ii1^TZSy|s^?koZK1H1_+y?Dw-Y2}{!DuJt6(;}=7C#Vi%U0IO8fu0cPZO? zvUzdmg6OVQPi=TKZ`XJ|6@RtPuDCBnYVyRDr*6B(Jowecx?zW@kY#l2nw*UE_FoUT zB^`EhXt6y0JygL`(mLty=7}~h|7^cIDJkNj@-ODiorm2{esTJfXRfj4Tu#@E$2LbU z-|b!|zTN2@+F;;x{RCmgVu&^JSc#x*WaxP3qv$<$FU#rYur@crM*nx*||9@%FN4y{oTM z(zlfRe0&_Vp5gI+XQR!^fs!K1SNvXZy*MWK{{O>#x^Zym7aYYP9jtGRRD z8;chqddt1IND60UtE~|&nzVHP zoeOgU`WM}LWwKQ6id^-r`NnLG_kSq#Fz>x5Ub=VPXcU7MEM)#9DL>+|J+y3=4Qmd+$Yv@jo|ui?}FWYQ&;!>aPJo2RF%4X!!KRKwl`=M zw~1KmnwR(Q+L-IV%ece!XwJi#XVtgfs%B|jICb`G!{;S(1q(XD&;7U|E%)qaj83}j z66=S@y&UZ2Il?M!#V$p{cn4_=<93_mD4Y?PFz#4 zx_hpmc(1Me?d;a*F`2wnJO~PI&`YuhOYPazxTTT zh+LV~cX#@YdDf>K+WMG6_E}!@Q-8-5b4Ppb@?4v%g3EQ^Oq^e6_PhO<@ApGje*2qc z+eV%)KWp~m)2kH|Rz#h=nA@CsOeg!?Rpn#*Zzrs1>$`J4dew2U{cXL4>esBTShgO> z+^%eOnqS6lQJuND{{KrI3bpzgORQckU%Sk2vivTQ?KOLTKJ`zZ+`!Y%<){>Cao%H! zfeM%EDkCW-2gbE4zL)b@@}EB(IpNFM1R3uTtDFY;9Z!Gnz3DaC{fT9<$?GDn$}VoF zMM*{??RkmMJ>sj1l`h2Cd}~j;^+>IKg0$m8U$3pqOqPooExq@={wnTt{=tpvDXM=f z_rKU!U9_YBF{9u@GZi)8w~XgkmKY}7KbOMKR~VgpV~y0t4Zr_Q|K^^u=>fyaSMoj@ z%}1v1u4k4Nd){wzW4ZdPcc-0f=5PyV@3}8?a?@{>rkpKnwqFyOo%w3^O~Jt6BRRk3 z{9fx-$lyf2o6!ae2_mS(BN!vRJ9@ec538`Ae_e zLSJ{mV;p<7M||7lsu7;v6~enF_wnhM0mU6F*_Oy3HcWr0mft3j$aVA2MiuqKXUi{X z+5Izuw=}OeDNv|(-Ed`T z_Hzaewb{L`ohLgF&z;Ltd*Sf@)>G_;`C^keO}6Em&fqhe-&%E;W7ceMH{++xLy85wiK{?on`n&tJV~`q*#!d zptDZy(85Q5{`fpt!*wtq&fT#|W@^?;f#-j(aTK1NlJi~Bk}K!gm*CHm>=jR*uVFEK zc5d&^r6=>W|DWdiZQ;khQ|T77^2xw3me!*Jtc$<@-hN_+M3K;x7YmGL&G0;Zpp@^Y zeSO?guQcb+OMR{`eDvn7YE}BQmU@GPUe$)fULwMb*ODi{m|F02&iSbS^RCZGGR`|A zoSy#J@n`s5mDH?htNk|}Q0V@0f#Gb(udQl3mY17uoxd||HJ|B|NUk?bIYvw_S3J48 zs*SQ2y3MX^4XY^(T50c57vbT&%KygAKf<2>SKStFk(ltOpfIvQ*xqE9GwC0f4 zX%@FdD{c2&+t;!5`JM%duNK7!N(gOXW0*nYPs~=X>S9ky+7y7iJBHV-E+nNv_+;rU4OejTD-e@XWe_AO>-6q z?AZRNNiS@9Vaw%dlegQL&A&5|<<7F;#ZMITZ55B5%zb{He|<(47u&gG*$cPF#0YqL zcvuM>xZ?A1^6&b?iU)4bJ(n$%>(8*+%YC}bd-0;%cXni|p5Kvj_S_=NPii6I#-1KL z2l-EiE_Z9@f3U-uWv}qB`FZKUq5u(pP-nkEPKv$*v{s6H_{Mzw*1{&{v+KE4~o2(@g@AY^Q1gdQ@Y*Z{9a=cBf{}DE@29Z!327XM~zFFfeU;vm)z~n@O|p zihrV$uRd5+y{keyS!SK+_Y%*&lNn2P%-+!9oUqYrA9v@TeP)Hl>h}~U$o_xXY2L{s zTYf?Cq6u|x8K{oKYrDROeVz*LGHOrT2^jyS@%(*-}SKmT;eZ~4^^9M)%w0Aw zqf)a$b`o?|6NHl%&?sK#MobJwwCb+cL}%mpB(xlg6G#)ryTrXBAat5 zR;d5|dt;w9a?*wqpSYU)hBQn$=3tQa{O{ecUQ3&u*B3ctET0dL9sGfxbCIJv&M{}7sxer4^Qp3g^Cs+g8faftph&-!V(*HPw@ z!;9)~E9Ymqh(@Yyss&5#*ZyRbyuHc_l2A}VzPJ71C3udPfiK*T&(ucNAZ*L z#Un*;q))i^)U-;y%wpMZ8Q!I%TAjAzZE9;;Ve5e^ri{0Z7Kx|W-@CJandrXdVp_k6 z;0*towpuZtGl#2!c@`8#PzTsG^%x#^pFr%8!T7H=>}txLLnej(Gj}#5KFa#Z);LSp z&#KDhNX?A3tto4!ulXmVZ5hE%*;miMct<) z> z8T{k;jXz8kvzJ}FvB_3;-@2`HyxM29Kb>RL%4k{e?N4x>ZLYmjy|3i#EgDlQ<5%-< z+_GiS!sYTOirV$Kx=+oVnV8G8HSt{Gk-(On5t`rT-h0lsIduM{-i@9Hty8A|&z<74 zTWeY$dxLT1@#2<=zayp?7(PFizOALc!YinK=8@>)-lw)Z`ua}A?BBQg&@q3BIWs@C z3Y0Pn_oWD3ZsbVy*)uPi;oJ`GE_&Ygx`ZLB)pXTHqEu3>-(X~z^*`Vj^E`fxOZk@a0Jo<6G zhu4|LPWrH@ZTi&9x;iQ=Gyk}>@(12(4o-L-m>!+DV)rx71vmHAw%XsHyn6lJDed+1 z45akj?kY@J|36+VVM(}Bm1mEhx6;j$Z$Hi@>TYAM6ETSKc(i1(pD ztQQLY4ml!vFY~)sN{EW|>;@5=k1ipLchCBN`Qr5aCwvTR=Ux0Q`>bnEQJeWIiyWne z>busSFYMiLE_|0~tS{H?|LSXGO&Uu~L?3;Z?Yi6Fn;g#g@7W2fc-|kX;yV7+hQvf55h^7pSV zUh4~)udC0>c=hIzidKKy+WWKQ0)<4)c#f1@%2E2gM=$cyj3WId3)fzWk+xrceEPA! zJ7-#Zx6XX@sZh}VL(SfmOHQN(CosnIN$#2N@7-2;BJh9F@$Sho6$Zw>w*GOK^G@$@ z`DlCX%4*#Prbqqvr{rbV^hhc%xu&qYx!kK=QqN3OiFpabL~fh47s4H8U7n&lS^UMy zE;-F(`?aO_S3UZCzR7Cu?kBG*PRK`b+%x=W@o~YY`?DQx+jDOB{`_X2u(9f9CMT!- zxpU&~>L^F~xJKo*r=FbIbDMjLm9wozVNLS3(XZPFTNRPI$?R0L8z5w~2&4FFB>HRhM4%>u>eT zeP<^A=)CZHt=E(lqSHN{7`#<{m`HiO+|s}K8_56}3)lVB)){ewkp*Oy5b*G&@t z^2u$n#tF6yzpSH{EDYPvyr}a2g{mDBoDQeQuY5jb0>4Y$KK;APTWl|#_F7T3XoAz_ z)jN$(J5KLwUc9?7VUo)2XYuLNp4)z&A#M{Gx2RS1^+{9ix|)g6i|*~S{W|yQd=b4_ z{Xc~5F0iP6O3q}oiF+3ACqBu=i?f`E^PG08dZ@p#$f1S_HJ7{e55+DvwBqbPt9dc; zk)5h|__;Y3JIJVj-5Vb;nV9OA zmb{s`^?YM>Wy%7Jt;mc_O${QgTwZ z&q1@3e~p>QH?{TbM?cUCK>fi=>sWnv-#7rb6T}+Dn;@NYMfAibk$E&pOh_$|6t(5vqOY^l? zaKayt?PmM}GQIwDE^SkvGF$qIg}5B!^nZfdqFyJ9_46Jc`qQ7p;F({pbzrU99QV58 zyNeIEwt7rC;Iqz6%VHj{QtxB4%uUL-=4aO1+R4smE&8USP=DV|BJILqk-5U@656{= zJ<8|lF8TTCbG&l$gx%|>ICEdLTK#*{g$!9`es9%t`~hrB7~Ofom-hD68+~vOT&j`$ zsZO|FA!mwWjjR4t&b>Q-B^wDPMl~r{8{XKkT5D_MiH{qN12-oT{<^?cLty!db zqW$LY*a=QdUB0hppZM~gvDj5*-I{ODX7kiVfAEr-IzdR$dF!G2-CIBFO&2>eQ6z2q zwRx6~^Btr*_ln*AIJ+gV*{9R9u6*wN_?X4V|Hh{-nzl;hzz!EBm6@7z-y~hQ+TE!- zkAZ<{>w#c}TZNB~1g|ui%lhm4%A2VxoxV?J44>a0JLk{bTX!}s*yt(EyjJT`dYb5? zn~VAuO%QqU_Q#6WUJLg>spXSN9S|=T5 z?EYOC6=&3AC|*4KaZ>QsX01P6*#Tzqolc)#A3YUPrWjL_;G*FhowmIHf}(K0_v(Ck z?+8J~6(2Gi{>(o2d4E&MKFPNyR{2R@%U)Fc`Gt#L%A7?{G>?7zwshn4*5x&JmZsrT zmjx>22px(KuG>U5A;)|x zc#g|kNzykY{?5K-(~LGtE?r(x$$M?}^)g+*z(tRk zG)^TYpSxf<<-(MVzscOkwjK$XaV1M~MI8I>z(tq$PGb9avO8DgQsNWy=6UV8k1nt( za%S0TJy>1haA~E4Rc6sTb=CH~{JDCEZyfl+wJXlrBE9o$=HI&6C)l@ai#->&uCwvl zryH*>zcl%>_4B#-ISbQ1PS%mS@?W`<=~!CO?*jAX2ZPlQ_ngR6PwHCqG*!mmWA%}L zriXs#_S}5?OK#_}C3;^UBu$*U@}hG=zSsHb?cFzL-PmD!vq16Q$K}Uf7F}j(DvLht zC&;GSBXPadzMvO*;fV0W`CPx`?;wqzxl-Bg!O0K_wh7k&7S?yGc~-QukFOA zR6WfbPlbe(#Q1A}G;Hk8Z^~z9mN=5Tbmq!*^RwwSH^u+GSabiNqjM4aU8SnFZy#-{ zmH95p|BDa*`Lpfvic_c4E4}_KH|(3QRjI0W`1|i3>nAr?zh&|eneurq??OYyD1Phh zpC4o#tiQ6}+F0;c@&#!R)zy>A`5x_CP;j(OeX&-i;(f(MpK^`nPWbsMg;Ttsws*4s zqnSao*pmdTvOOTqVeyR0dZ~q?e+;(u+M`ov*CmW_QFfeUf9#wW} z-!wzl^iK*e10L;sZ);%G#-O?ApxV>f%e|b9r?$#Td7iqV7@M(AzE|Eg!ggkDtc>== zqaA;LN=^HF=;OZKoy)j>Y}mWAuuc2gg+&AI@13j$`?v2f%-r*=?aYCbe?EI(_Yz7FOb&|QseWftWK(|A4#|zz zs%J4h{&mYfi!tc$>suer-i~N**zk1@-@iPEz>C6Z9$udx_j-2xKiTyAO83*wh+1aF zC6nrx7bS27?VlDm_2YZXZ0*d{MGw1X&NX}Pc4YST;;@V>Va&lA+JEv_X7b$fJrTZn zr&8qZkA1dtHZ$?(+x+M<-Fs!flwOC6b8{fWiWT1`-d~<`o5bD@=a_LP)ujHg?DLto?rKS6@RgI=>MQ@o z-Yi|}Yr*sUVBIpAeK9<7<}A1F-Zd7Q+T_`Oq9E(yhLgU(-}KxJ@Zl+HC|!EbB5a0- zp5DBsOz)NY!bhu`ZD%Z#Jz~Cj<=TboTsk%~t>F@!c6sJ4`?Vg<|93`K-&(8oY-Lf- z{2I2G*KfXT7Q4o8;Oe=uXR(je*E>8P{$ILr!gBwH4pW(uTWnMPCH=zBJySWqXiZ7& z8z-jUCEK%l+_d@h!@Z6#f629$nK^Uf{+UmwbU8*G_%tQ?ZEvRz=RA*TT+ZgENfM{m zuQ+ky+`XFJ55vu76kcTXV7{QSQQ}O!cE{JR>!Z|rW+(`79?$Sl)8-J$PU;BONWWFz zxIAEK>E101YHw@B6m4DeO0JS~g?pBW#21g56>GGGWpp-dl#ub+`|DELqn4+KwN7iE zn6OZB@w$BiKO_8@z3v@YC>H%%u(-~}Z^i-(D`S0w#eo73q`ud$x7vJb#;iQS?*>oL ziiOQ{P(A)8Sin@*H}}H7`01so;ZuIT)>wQ?c`5smqtiJ4^*x(Vu-Dl@^~hEGoQ5qd zOZ%kKyKJA>OJ+D;2@(+g+iUhiG%%GVIse zp!OFJmNH34m^0x8SL0_zvcB}q#K*cD&Z!x{ z)OR=EU|4E?dhWjKDcipNd9-)ox1566Z(e4t3et(X?uG)s3W0|V3cRmU8T=E?m3U8-$6ZE}CG zp0}R;r@y&kU$fUR+&O32x#VZFY;de8G& zlP0EmzOguBcx?4#of(e>C~Ywgz#rLFJu=3U7%`_Z;@ z-^MeqCN3 zS$^VvdTZpa-P=81nQ%^v$w*e&@@h{;{$+kO-ZRQ8N?%!695+6EH!EA7%R*>3$I<)_ zrhc_^b6#;Iw#7`i;4Q4Re`x~uBDdFt8d9k{bEe!(S-YO=0o#YHhyF}!Ij6BTTq{bh zQMbu1RW00de2#{$vi{Fio8mbyJ*${xB)UjgBjr`77K@qfzMm-<{V%;=b8oV1iABh) zBlfZ%C7!nb$>S+JRCOuGNO9?sl;cKUdyQII6s%KIj>xDUx>a}6;XV7Sq9X?~7S_(v zs5r-1$RU!x_ibl)$OX%Eo`~6w|93jwcjeJaz5Is9KxmuD zLZg=}*`z#W8oMTK>D)2xc}`wd$5!>nHxE@bKE5Y=o9p=8Lf^YHKIDAg7#(Hk$Yk@= zF|7K`*_hqGYty_>xqQ$09Of5&#Q9P+OI+#wqcTEyPQh$yJmP0dPF~tQ`;kG{$*HDS zst>ZEjY%!7}H_e;>K@1G+1fO-27Iv9%ZpDqBWHytz^L;y~X2 zbH8|@^6vUrY`$CoN3YaRUc0+X;E;!^!8qJ}%tYX&x_~8HT=l(S+nxE%W zHE~NZ%IJMnb#A37-R+#h=NxfP4D zCHv|P&B1d{FZ*ZNR#W$9*SEwNR|o!Z+2GIT*DLG{4HP-?=6m_HiDHG;#u*boE}j2D zNaEzwf}hjAW?%0S_1L&NXy)g-)B0?_+pOVDgf}4?A*S7)0{ubN;vd zb$W^|yTo~(&fp%@c0fq~{O*MMj^J4!GRQZm~k})Q0F4T5M~JoA)}s zINId$+ksb>^JI+ViG8h(H!P0?uw1C0BQ)9nu5aMOKmJ~>=aZJE?_XHPI>FO%Y28-uH2UVGqZ%{)n1b4ecOM1BqV8(je0g&uDmXr8 z#q73jmV3;V|5m!5QBs_twPtC|l;)gw<<;H|bIRu_%yDy`S^2YX`;E}wit|J2ZI35; z?cFVxa_;VezNA6}5ADba`=(Dd-pt2xs%GAfze=u+W!tROSFP8tc_VY@$`dW;HmzCP z&o-`~>J-Poz_jy~gw}BtwF{0mN4(eQd^lq?zteNBF3an1xg~RUoJ}lIa_2s5W)WZfCzO6=o>)`Z8JO)8^y%Rd*=09oX}GuHesE;ggLV z8n%=qu9+2Fv;DA~xHuxp3mz(ha}ge{EBi{=TyCi|`3=^Nw;S{!iLp=D+{HCG^yy zbeD7^Yu;yn*ZSHT{?(ng#;PfNNrvdTXCKZl&lFv_>#E|XtpZ|PAx|y7 zFEw#le_Xh5!qm)wNx=%P(Hp)@esfuA`J2lxHm`KpEy`V}&o44je~z%+KheO(`0SOg zsZYO_zK=LAX|!aSl;n)`**>W+PncZSEuL(;A>Me?-;dwDyek)3s$4qUuw~`to0g7t z%7-#8tU5Qz@t3=qU#Mf$jj0^l#L{HkZrpg5vweM>`->TFLdUv4u>S2c+vvBRt@y>+ z+pf2`H$Hq~Wug(g;LvAvt}6;sTMU1_72Dn27U;mk|7-CjOGaafHy6}S);%vPU;F>Y zfwaBPRbGV1crZ_2;rRTG)ZuyO+NvG*6zfbWN;o;E{#4tq@Wo4Ch;nwmW%#&_Yi8zr zIq3(97OqTn2d*b<>{Xw*dKu4p8S`5n-m6=9L_F;uoC=>|-?PB2xNeVf0i&q;`*Wdp z@;rrum(1lBEe$$9Pn>CU0&|mywu{iOXKlNm-&8PKJJD!;ovy5oX{!5?&vQ0;XsX9m zmN=~BUv;t5y6t-3^rQbIvz^vWP(Hoq^J$&-jkb~UjBeAW%Pw`FF5k1pnkOjcSM{dv zj}Jd@pEmvP^?-Q!FVj^QFIyG)?Jw)0bW20SpvCiM&EgTCC&g0zYfZ=5PA=<2`^zp< zmy7lP-QfK$g=zY?Z6Y0ig>A$tUJ9rb@y=sO+A>RPZ<^25_Jhvz{Ldw;xEMduWYb$~ zS@LS-#;KEwmp+v1T_DtcWZiig=@Yi=r_U47`x^T)sBw9upkn^=_pi2YS+>_*g2j&C z>q}Q`>&LGFv*&lqbp~X`OclHR+aTM&+_1TjMR4t>S5xFJUw|O@FUYh){EEf-?qLdS1?g@#jgb)j8C0< zae(!QTYh_O=|f6e*VodJH0Cc%jc z(&DFlE#8&vmoGNoGxeG_vufGwhZi4-@jA|*&RA1lC-@_VcW2uAHGVOk2XAK{EIqb3 zH_yjE^T)N+)~pEy(UXqZ^4UL~9W|XjMPNNo?vF(qULCVd%V)G%_Wi%(tE{@9{-?i{ zoM$@RU~jVQw)xC2vZA^5$REGz{VTtok)L5^^kJ^O%%#nz4n@2PD-oNmSAL^4yxF%v ztF(^q>oh;Hj#SPo>jLMU3dvgOy-xCW#aq5jOfTB=*kX)!d+d6BeL;6}S4P01vuka) zd5Y-!@B1pL^X61fURm&=psy2yx^4fdiI+0Os{K>1nN(l?eZ%Qyl^YLj_gmHp;wUelMgB%Ob!HG7CoD_|5bqRy^bBP-|v{Dl5x2}ZrQh88J8N*O}1UW z>ePg9Z`L?%-)_I!maliiJPqF`nir=evG1AiWQ9*8|FlD0bIl;AXT&C(BVyA!$=-;8e0*wp#;R(y34+lz-@zZp*)J9E;> z>oh}Sg^Ql=zePToQv-i44$@WYi*eYrr=a;t`o(z#Y|O&PPyG88qUj(%f5M*^%BeC- zSr$&MD*t$JsS8;S~^4P zQxJD|&7rpE`o*hH>+h_ry!rp1p=$D}d1}SBQ44#$T~wNwc1EmJ*L${CQ8qPox&NQ} zYby_NNL`9Q8>W13k&6k&bes4H&r^yGw8$GRJ+a7qmQ+~k3y#ID(Ts7yJ zNvFRG-j6U!j&(C8_?@uWf>YDue5{^nC?!-q&YkAxI%8_7VV7q- zZ||3{4?}01$dTa2^Qlv=yK`lFW$)a`sOQx6+JCcmfc%bA%f9(>D{bzQ1a{updE9Y6?{BvL1Wi{W$$J`bR-}aNboz+vEblWre_O{&H zd2@tsZ~Of1`~Lgs`}o(JX0P9x9>2JO>#`IxW3^qk{+Hy+Nck1H(^v3Htu0Ppu<_KH zCsjRuCQ`nKirwa(s3|G#HJmx`M1|dqig}-2D5>kYPxTfz)RA75ce};S;$>bZE9X*dED+F67j~mt7q$R8HLGBeehFQv2|7S+x>#4#iW%ktNC5y zUXn0#%kQTQvu)%|_kDOF8zwe+%i*oYAy@MqZsiwLX;vJ~T;b^%_WBdszYJO1ypFSR z^;f2aOqo#Jb3USO%X;O`v)~jv6}m`+2s(TeDJ8E|Or|~eU>D!@U7ST;@8*?v z8<)&ajC$++?e*OwK9|0y>UeaWk$JZ?@p9li&08!BAFWfmFClVq%ABdC6AA@6S6EioHSU(Wll3Gsa*1$P#XE zX70IaExXOUd&|xojMQK%b7MH?dhfE;+^(mU{QMm&_DSv5xBN8o-Orxh`rPXJ7n2%q zU*CQ|U(55%dcB&u1E*(+?uz|8H*wcy+lyN)f0gR)IrZR?rg_5FGhe07G#>t@sp7ss zswru&^vpHO`Sn(_oGf#zEcuu^$#1cv`6r!wGO4e>9ow8bw`_Mos_li3`&8Yt%5N!6 z*}QtQOc~3&iGQyIv^=U@v$8<7wPl{kzo~{|Atw!*4^Mn@Ek5N$a)UwWg_|6<(>27e zzt?&6?9GurBLzvfLPp{FJ}vc|dFy!!dgo^@{;_z&ugkxS?ILa$#&`VvJNJFsD(gIv zGjBityq9^iXUlVSUw)a_jtX+1q+K=aoM>n31oq**f#8nu>c` z4`b_{S>h6F1CrhgUiRr`(s^ve*YQKO@iXIo?GNS0MPmk1`wZ)MlO?A09o0B%*6)cSv z+0D+@XV7N&pvhPFtm`?$GR>5TBYI4AE0f;*x%}hK51$p>VQWt|T&VY({I#ZAcUGX- z0>vd~+Pc2oaw~RZj!eG1Ki8`2c)a=k4GLT==LGdnUSTYgk6IUf?dP&!At4nJ-j49t za||mM){B4hC&NN{jSe=Hh)NRej;)4H(!4Gv*)SLoM*_of0>#7yrEHd zk??YBE`95s?Ec3muKvAd@Z)bU^Yv!i4H*kuuD^I+*_66`$2R8XosCh;mU(Q))Tg;BU0;vD1oAh3?++vAFc%VnwRLxeV!= z4XvikDS|=u&pc;DPh@>`_CkN-=dJgWX1o0s<=Lwzx1qq$xc}8ZhZ`Y{k4<||&3kij z*6bnfri&L4w{43`~1h^*n97f1!E#O_e>?GuRg-)g0B~pYC@vOut0fr7{1x z!CRln-z!dYtybpU5V5h8=jF`X?Ke%5W46n7BLB1GjCg2 zj`ixA?_HZ){`&OsoQU3Va1F;lPtUA*f2wZUpLng=!d<;)cBG7Z$Ez8UHp{MQK01Bs z%vpbb9%gO%$Op`4{wy%FkZd?C_~c7)F^|okS@K(_Ydf-et+F~~WfgbxPtaz0X|YUa z%ccq2-rlO=(@jmS{>@&w{7&bpRRQs=f2$@63x__RZm}&ZO!THfg0m`vlalwsB)`6z z#MCKkWX>8EN@iP42u@#h?zVf$HZLA)zdbMW*6)c4JQDoYX5r%NQ&bWx%agx%ybc%Y z+!0^P?9IO9&!3O1>+aj0XlLRh9im-z62Bw%=g-s9w9} zC|h?=Du>mlw;LmWYRIvieqbbRm~l5xrbVUDXpU>(`u`$pJRU6h(WigthRxo-5{s3O zFQlyXs+hTS&eiVQdsUuYw^{Z6<2s+n6Q92&x;lNAe$8VW`F+#M6jJ_lbgSL5Qa zd9)~TZU4#g!q(j{Uj6vknA+cNe_Ye1E@JzUS1by8=pZ?>(C@6r^wx+8yChwi1x zucM?jcTEf})Vj&sv#YFUQL>zX<+o!V*NW%*EjaKeC^gzJeg8h?sq@c1=(T-&X~F>& zEms~Vl_~48j#tE0+z9a1zq#l6tGd|pb=STt*21& zinKs(i0Gv=Gpj@R^gEjD_s*H8{Wtf}r5Ov~`ZF>$vsiD*X?t;IV(dZlL(F{g-w(`u zcP(OKlHpg+id)puG?~GI}J~QL; ztX1{V3=B;BYTA^SpN{*$zq>f$Qksi_(vx5l&m)W<1mlx8_FX^ACujVejX%^Xdth1#q0&KmGrtWt}S}rcMZmyDanW=GnC=dp}Mq zHOh!%pZu;d><+_64nr^9hllc$cc{EhomXt{+TO|Y=-$=t=AMl6YWsD*x9?I^TT`s@ zS3IU@ms{u?%>#Z-MSz6rmx{GI`q{$;OfoBg(JOS?m9Tp?n3e&7H3StBZq``oxQCRppkM zUn_eW%^6(&c~Yw9Ik$%g?KN-aE!m-A=k@!}Nzwm1_fE{4`?|_;=Zl{V<&n9Yr`~xx zRlxCi@r)Jg!nc$f-3rV&YO#;6&6v5uh-Kd@-A9+L&7Usm*tq}P@pJEcC;Qck+HO7Cz@I)zIP=figR=2%dM$g_Uu#w9;eS_>!`|Ne%!~bWGt1_pRmQOo zRh(;Aix>U4aLeIZZ>RK!DYNRn@H|Osdj3!2%&Dl4+4)xc56yg8a2X8nq+#pcJ} zN3-#82&)@fz^!#PW9yYbXO!ZtQKbQ6H^uF!OI-Wg zsk7-TRe0`co;FCUVpu8r?x*`Q2BpwS9Mw$z(rqX<58& zj%S&xhs@eWi49s($F?W1xLL5TY1*}0I=e;L+T6&>%g4>FOh7~`!0=GItaO;0$;aJi z7SF#p&HA$U?5BlWCU!7p_mv*o)F~o5!%j0Tx7Wkfw9EGMZ{9nlRi07-3=B;BQ=Y9c z&9RW3KhYrHcw%@8o0i7E=lUu-TQbztU(UN{Kkek!+)1V;9Y4*Nyqy|Qn!9E5LWwtZ zN~~;k&5GNe9ufC%k-W1v?TqG1$#cfpY8SjB&)qe6%@(|OotpE?8>wsBcJ+5yzud6o z;*qpFoeU8H$FGW|rMM-na9hHy-K*~|eeUBkv;3ORhXU4I<~{1_YPfP{;N@Sgy`qKn zVTXctI%k@k)6RM@>0`;UW2Te83Od|h{YhT+dxN{1Tc>2i2APJdp+avQKUp#N-`iI6 z@6@VTpFNSO-2$o>^ZNN;O06*~kh5BqzAN{m<(Jd*r<_S-NSYVhyV^^xv-RKRi&suM zP0qaNVzkIExz|qW@Vb=>Ntb5q|FNs!{>AN~r&(Fmt|&}6yQ1v7VTiiiu3wMsJ<|_t z-W!@c+cYa@=0wZpzq~EYALrVbOezowi3we^=F*WprRE}E zw}_l)i+boJV_=lzbL_ab2EQV{Strjr zgfDos^Vq*bQW-yX^qkFZlIfE8mHN(_>-fd1TVH)Y%2^T|zD1fd^0@wy$}7BjjZK?& zx`<4WI+JEL?U4DuLl+jjS3dDPwVm7g!k6Q37_ZdJ)W7u7PENg&>lym-*BNd<>Hji5 zldrfRv$}Jx;6Rsk$HO~wIb050om8+jLCH^TR)1UV@6*appB}p8e&JnO`RjW}xBTCn z7d!dFE${l^w2*+!%&RMHIa)cz{6A(#hxpuCu|-9sd&1#OHOHz%)+V2koS5KTDRbNG zQ?}se?H7dH-F>QhEnKRlQ_9yI;V+vh>A5<5>w0}I>#(3{2QS@u^LS<24TIwJ@6HR1 zUHE^hNL8Ha&)f2?e@4Y`Gb6tWpIi4$!+VSM%&!MXTd=i+?KS9lX>{`HOi#}lb-A|B zzgNzY)SXrkwy9Ss>`V4F?@342O#ZDRCe-oP+q0{Sfr05jw$Smy?*X5czB#5e=igh; z_AGwlQKzQ7JN~CC80tibSVs8yGn=?(Y)p|8$O ziLL$9ZTNfFMFAZ)%VrH#-LJbp_kMW0L(p?lgT3YY{v(&RU)X$jqF3GF?uT2tgC=kY zZOy4EV(*ma*plp(zWvnNMYHYW7u8yx=~OM>7cs9x>Tt>T9UM`GD~%<}k6o>Kp2AlY z@qh8&86W<sPPuux*oZJLkvwx=i7M z_3yjxC*DgnpEN%(KQ7~6#n(as-&EJk1zQu|W;!%{T70fg7=S|D@FBU!h{#e=VE1WkkSB2dQI<)>-*5wO-*Ij)7m3s}} zABWq9z0>4A|7NQf)O1pseD?pmBxWJy)>q+Yiv2Gx7g^}?J~)y+fJfl5VD`GKwnGnQ z%0A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