mirror of
https://github.com/reactos/CMake.git
synced 2024-11-25 04:29:52 +00:00
Merge topic 'AutomocForQt'
920a046
QtAutomoc: Eliminate compiler warningb00463f
QtAutomoc test: Pass QT_QMAKE_EXECUTABLEe78ce44
Fix automoc with VS builds: apply patch from Bill71165e9
Silence warning in automoc: use long instead of int1879bcc
Fix build: use std::ios::out|ios::trunc instead of std::ios_base::out678e124
Only enable the automoc test after checking that Qt4 works71c29d1
Fix bootstrap test with automocafb3edc
Fix warningsadd30e9
Fix build: non-void function must return a value7e6d845
Automoc.cmake is not needed anymore2963d0b
Fix logic which decides when to execute automoc test77a5c6e
Add documentation for AUTOMOC, add initialization via CMAKE_AUTOMOCbf8ef77
Add a test for automocd045fd4
Nicer progress message for the automoc target50cd6ce
Move automoc processing from add_executable/library to cmGlobalGeneratorcbaac2a
Remove trailing whitespacec27607b
Refactor SetupAutomocTarget() so it can be run after creating the target24d9b7d
Remove trailing whitespace58b7fe6
Use cout instead of printf()72caf4d
Add the generated automoc.cpp file to the cleaned filesddb517d
Color output when running moc9303295
Initialize verbose based onb the env.var.ace1215
Move code for parsing a cpp-file from the big loop to separate function735a5bb
Fix line lengths83b730c
Add AUTOMOC to the add_library() command126c6ea
Add the cmake module required currently for automocde91feb
Remove the need to check for .h/.cxx during buildtimed65689a
Add actual automoc code from automocd1c0a5f
Start implementing skeleton for automoc in cmakea65011b
Start work on automoc: add empty cmQtAutomoc class
This commit is contained in:
commit
39f0fa725e
13
Modules/AutomocInfo.cmake.in
Normal file
13
Modules/AutomocInfo.cmake.in
Normal file
@ -0,0 +1,13 @@
|
||||
set(AM_SOURCES "@_moc_files@" )
|
||||
set(AM_HEADERS "@_moc_headers@" )
|
||||
set(AM_MOC_COMPILE_DEFINITIONS "@_moc_compile_defs@")
|
||||
set(AM_MOC_DEFINITIONS "@_moc_defs@")
|
||||
set(AM_MOC_INCLUDES "@_moc_incs@")
|
||||
set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@")
|
||||
set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/")
|
||||
set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/")
|
||||
set(AM_QT_MOC_EXECUTABLE "@QT_MOC_EXECUTABLE@")
|
||||
set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
|
||||
set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
|
||||
set(AM_QT_VERSION_MAJOR "@QT_VERSION_MAJOR@" )
|
||||
set(AM_TARGET_NAME "@_moc_target_name@")
|
@ -228,6 +228,8 @@ SET(SRCS
|
||||
cmPropertyDefinitionMap.h
|
||||
cmPropertyMap.cxx
|
||||
cmPropertyMap.h
|
||||
cmQtAutomoc.cxx
|
||||
cmQtAutomoc.h
|
||||
cmScriptGenerator.h
|
||||
cmScriptGenerator.cxx
|
||||
cmSourceFile.cxx
|
||||
|
@ -58,7 +58,8 @@ bool cmAddExecutableCommand
|
||||
}
|
||||
|
||||
// Special modifiers are not allowed with IMPORTED signature.
|
||||
if(importTarget && (use_win32 || use_macbundle || excludeFromAll))
|
||||
if(importTarget
|
||||
&& (use_win32 || use_macbundle || excludeFromAll))
|
||||
{
|
||||
if(use_win32)
|
||||
{
|
||||
|
@ -31,13 +31,13 @@ bool cmAddLibraryCommand
|
||||
}
|
||||
bool excludeFromAll = false;
|
||||
bool importTarget = false;
|
||||
|
||||
|
||||
std::vector<std::string>::const_iterator s = args.begin();
|
||||
|
||||
std::string libName = *s;
|
||||
|
||||
++s;
|
||||
|
||||
|
||||
// If the second argument is "SHARED" or "STATIC", then it controls
|
||||
// the type of library. Otherwise, it is treated as a source or
|
||||
// source list name. There may be two keyword arguments, check for them
|
||||
@ -85,11 +85,11 @@ bool cmAddLibraryCommand
|
||||
}
|
||||
}
|
||||
|
||||
/* ideally we should check whether for the linker language of the target
|
||||
/* ideally we should check whether for the linker language of the target
|
||||
CMAKE_${LANG}_CREATE_SHARED_LIBRARY is defined and if not default to
|
||||
STATIC. But at this point we know only the name of the target, but not
|
||||
STATIC. But at this point we know only the name of the target, but not
|
||||
yet its linker language. */
|
||||
if ((type != cmTarget::STATIC_LIBRARY) &&
|
||||
if ((type != cmTarget::STATIC_LIBRARY) &&
|
||||
(this->Makefile->GetCMakeInstance()->GetPropertyAsBool(
|
||||
"TARGET_SUPPORTS_SHARED_LIBS") == false))
|
||||
{
|
||||
@ -103,16 +103,16 @@ bool cmAddLibraryCommand
|
||||
type = cmTarget::STATIC_LIBRARY;
|
||||
}
|
||||
|
||||
// The IMPORTED signature requires a type to be specified explicitly.
|
||||
if(importTarget && !haveSpecifiedType)
|
||||
{
|
||||
this->SetError("called with IMPORTED argument but no library type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle imported target creation.
|
||||
if(importTarget)
|
||||
{
|
||||
// The IMPORTED signature requires a type to be specified explicitly.
|
||||
if (!haveSpecifiedType)
|
||||
{
|
||||
this->SetError("called with IMPORTED argument but no library type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the target does not already exist.
|
||||
if(this->Makefile->FindTargetToUse(libName.c_str()))
|
||||
{
|
||||
@ -158,15 +158,14 @@ bool cmAddLibraryCommand
|
||||
}
|
||||
|
||||
std::vector<std::string> srclists;
|
||||
while (s != args.end())
|
||||
while (s != args.end())
|
||||
{
|
||||
srclists.push_back(*s);
|
||||
srclists.push_back(*s);
|
||||
++s;
|
||||
}
|
||||
|
||||
this->Makefile->AddLibrary(libName.c_str(), type, srclists,
|
||||
excludeFromAll);
|
||||
|
||||
this->Makefile->AddLibrary(libName.c_str(), type, srclists, excludeFromAll);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1084,6 +1084,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
|
||||
false,
|
||||
"Variables that Control the Build");
|
||||
|
||||
cm->DefineProperty
|
||||
("CMAKE_AUTOMOC", cmProperty::VARIABLE,
|
||||
"Whether to handle moc automatically for Qt targets.",
|
||||
"This variable is used to initialize the "
|
||||
"AUTOMOC property on all the targets. "
|
||||
"See that target property for additional information.",
|
||||
false,
|
||||
"Variables that Control the Build");
|
||||
|
||||
cm->DefineProperty
|
||||
("CMAKE_DEBUG_POSTFIX", cmProperty::VARIABLE,
|
||||
"See variable CMAKE_<CONFIG>_POSTFIX.",
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "cmExternalMakefileProjectGenerator.h"
|
||||
#include "cmake.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmQtAutomoc.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmVersion.h"
|
||||
#include "cmExportInstallFileGenerator.h"
|
||||
@ -269,7 +270,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
|
||||
cmOStringStream windowsVersionString;
|
||||
windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion;
|
||||
windowsVersionString.str();
|
||||
mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
|
||||
mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
|
||||
windowsVersionString.str().c_str());
|
||||
#endif
|
||||
// Read the DetermineSystem file
|
||||
@ -618,8 +619,8 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const char* l, cmMakefile* mf)
|
||||
if (sscanf(linkerPref, "%d", &preference)!=1)
|
||||
{
|
||||
// backward compatibility: before 2.6 LINKER_PREFERENCE
|
||||
// was either "None" or "Prefered", and only the first character was
|
||||
// tested. So if there is a custom language out there and it is
|
||||
// was either "None" or "Prefered", and only the first character was
|
||||
// tested. So if there is a custom language out there and it is
|
||||
// "Prefered", set its preference high
|
||||
if (linkerPref[0]=='P')
|
||||
{
|
||||
@ -832,6 +833,10 @@ void cmGlobalGenerator::Generate()
|
||||
return;
|
||||
}
|
||||
|
||||
// Iterate through all targets and set up automoc for those which have
|
||||
// the AUTOMOC property set
|
||||
this->CreateAutomocTargets();
|
||||
|
||||
// For each existing cmLocalGenerator
|
||||
unsigned int i;
|
||||
|
||||
@ -950,6 +955,35 @@ bool cmGlobalGenerator::CheckTargets()
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmGlobalGenerator::CreateAutomocTargets()
|
||||
{
|
||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||
for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
|
||||
{
|
||||
cmTargets& targets =
|
||||
this->LocalGenerators[i]->GetMakefile()->GetTargets();
|
||||
for(cmTargets::iterator ti = targets.begin();
|
||||
ti != targets.end(); ++ti)
|
||||
{
|
||||
cmTarget& target = ti->second;
|
||||
if(target.GetType() == cmTarget::EXECUTABLE ||
|
||||
target.GetType() == cmTarget::STATIC_LIBRARY ||
|
||||
target.GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
target.GetType() == cmTarget::MODULE_LIBRARY)
|
||||
{
|
||||
if(target.GetPropertyAsBool("AUTOMOC") && !target.IsImported())
|
||||
{
|
||||
cmQtAutomoc automoc;
|
||||
automoc.SetupAutomocTarget(&target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void cmGlobalGenerator::CheckLocalGenerators()
|
||||
{
|
||||
std::map<cmStdString, cmStdString> notFoundMap;
|
||||
@ -1019,9 +1053,9 @@ void cmGlobalGenerator::CheckLocalGenerators()
|
||||
if(notFoundMap.size())
|
||||
{
|
||||
std::string notFoundVars;
|
||||
for(std::map<cmStdString, cmStdString>::const_iterator
|
||||
for(std::map<cmStdString, cmStdString>::const_iterator
|
||||
ii = notFoundMap.begin();
|
||||
ii != notFoundMap.end();
|
||||
ii != notFoundMap.end();
|
||||
++ii)
|
||||
{
|
||||
notFoundVars += ii->first;
|
||||
@ -1057,7 +1091,7 @@ int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
|
||||
{
|
||||
this->FirstTimeProgress = 0.95f;
|
||||
}
|
||||
this->CMakeInstance->UpdateProgress("Configuring",
|
||||
this->CMakeInstance->UpdateProgress("Configuring",
|
||||
this->FirstTimeProgress);
|
||||
}
|
||||
|
||||
@ -1161,7 +1195,7 @@ int cmGlobalGenerator::Build(
|
||||
{
|
||||
outputPtr = &outputBuffer;
|
||||
}
|
||||
|
||||
|
||||
// should we do a clean first?
|
||||
if (clean)
|
||||
{
|
||||
@ -1199,7 +1233,7 @@ int cmGlobalGenerator::Build(
|
||||
// now build
|
||||
std::string makeCommand =
|
||||
this->GenerateBuildCommand(makeCommandCSTR, projectName,
|
||||
extraOptions, target,
|
||||
extraOptions, target,
|
||||
config, false, fast);
|
||||
if(output)
|
||||
{
|
||||
@ -1272,8 +1306,8 @@ void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
|
||||
if(this->FirstTimeProgress > 0.95f)
|
||||
{
|
||||
this->FirstTimeProgress = 0.95f;
|
||||
}
|
||||
this->CMakeInstance->UpdateProgress("Configuring",
|
||||
}
|
||||
this->CMakeInstance->UpdateProgress("Configuring",
|
||||
this->FirstTimeProgress);
|
||||
return;
|
||||
}
|
||||
@ -1296,8 +1330,8 @@ void cmGlobalGenerator::AddInstallComponent(const char* component)
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalGenerator::AddTargetToExports(const char* exportSetName,
|
||||
cmTarget* target,
|
||||
void cmGlobalGenerator::AddTargetToExports(const char* exportSetName,
|
||||
cmTarget* target,
|
||||
cmInstallTargetGenerator* archive,
|
||||
cmInstallTargetGenerator* runTime,
|
||||
cmInstallTargetGenerator* library,
|
||||
@ -1331,7 +1365,7 @@ void cmGlobalGenerator::ClearExportSets()
|
||||
const std::vector<cmTargetExport*>* cmGlobalGenerator::GetExportSet(
|
||||
const char* name) const
|
||||
{
|
||||
std::map<cmStdString, std::vector<cmTargetExport*> >::const_iterator
|
||||
std::map<cmStdString, std::vector<cmTargetExport*> >::const_iterator
|
||||
exportSetIt = this->ExportSets.find(name);
|
||||
if (exportSetIt != this->ExportSets.end())
|
||||
{
|
||||
@ -1443,7 +1477,7 @@ void cmGlobalGenerator::GetEnabledLanguages(std::vector<std::string>& lang)
|
||||
|
||||
int cmGlobalGenerator::GetLinkerPreference(const char* lang)
|
||||
{
|
||||
std::map<cmStdString, int>::const_iterator it =
|
||||
std::map<cmStdString, int>::const_iterator it =
|
||||
this->LanguageToLinkerPreference.find(lang);
|
||||
if (it != this->LanguageToLinkerPreference.end())
|
||||
{
|
||||
|
@ -282,6 +282,8 @@ protected:
|
||||
virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS();
|
||||
|
||||
bool CheckTargets();
|
||||
void CreateAutomocTargets();
|
||||
|
||||
|
||||
// Fill the ProjectMap, this must be called after LocalGenerators
|
||||
// has been populated.
|
||||
|
@ -739,18 +739,6 @@ void cmGlobalVisualStudio7Generator
|
||||
entry.Full = "";
|
||||
}
|
||||
|
||||
// make sure "special" targets have GUID's
|
||||
void cmGlobalVisualStudio7Generator::Configure()
|
||||
{
|
||||
cmGlobalGenerator::Configure();
|
||||
this->CreateGUID("ALL_BUILD");
|
||||
this->CreateGUID("INSTALL");
|
||||
this->CreateGUID("RUN_TESTS");
|
||||
this->CreateGUID("EDIT_CACHE");
|
||||
this->CreateGUID("REBUILD_CACHE");
|
||||
this->CreateGUID("PACKAGE");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmGlobalVisualStudio7Generator
|
||||
|
@ -80,9 +80,6 @@ public:
|
||||
void CreateGUID(const char* name);
|
||||
std::string GetGUID(const char* name);
|
||||
|
||||
///! do configure step
|
||||
virtual void Configure();
|
||||
|
||||
/** Append the subdirectory for the given configuration. */
|
||||
virtual void AppendDirectoryForConfig(const char* prefix,
|
||||
const char* config,
|
||||
|
@ -68,6 +68,27 @@ void cmLocalVisualStudio7Generator::AddHelperCommands()
|
||||
lang.insert("DEF");
|
||||
lang.insert("Fortran");
|
||||
this->CreateCustomTargetsAndCommands(lang);
|
||||
|
||||
// Now create GUIDs for targets
|
||||
cmTargets &tgts = this->Makefile->GetTargets();
|
||||
|
||||
cmGlobalVisualStudio7Generator* gg =
|
||||
static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
|
||||
for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
|
||||
{
|
||||
const char* path = l->second.GetProperty("EXTERNAL_MSPROJECT");
|
||||
if(path)
|
||||
{
|
||||
this->ReadAndStoreExternalGUID(
|
||||
l->second.GetName(), path);
|
||||
}
|
||||
else
|
||||
{
|
||||
gg->CreateGUID(l->first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this->FixGlobalTargets();
|
||||
}
|
||||
|
||||
@ -2032,29 +2053,6 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID(
|
||||
}
|
||||
|
||||
|
||||
void cmLocalVisualStudio7Generator::ConfigureFinalPass()
|
||||
{
|
||||
cmLocalGenerator::ConfigureFinalPass();
|
||||
cmTargets &tgts = this->Makefile->GetTargets();
|
||||
|
||||
cmGlobalVisualStudio7Generator* gg =
|
||||
static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator);
|
||||
for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
|
||||
{
|
||||
const char* path = l->second.GetProperty("EXTERNAL_MSPROJECT");
|
||||
if(path)
|
||||
{
|
||||
this->ReadAndStoreExternalGUID(
|
||||
l->second.GetName(), path);
|
||||
}
|
||||
else
|
||||
{
|
||||
gg->CreateGUID(l->first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmLocalVisualStudio7Generator
|
||||
::GetTargetDirectory(cmTarget const& target) const
|
||||
|
@ -57,7 +57,6 @@ public:
|
||||
void SetVersion8() {this->Version = 8;}
|
||||
void SetVersion9() {this->Version = 9;}
|
||||
void SetPlatformName(const char* n) { this->PlatformName = n;}
|
||||
virtual void ConfigureFinalPass();
|
||||
void GetTargetObjectFileDirectories(cmTarget* target,
|
||||
std::vector<std::string>&
|
||||
dirs);
|
||||
|
@ -1886,7 +1886,7 @@ void cmMakefile::AddGlobalLinkInformation(const char* name, cmTarget& target)
|
||||
}
|
||||
|
||||
|
||||
void cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
|
||||
cmTarget* cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
|
||||
const std::vector<std::string> &srcs,
|
||||
bool excludeFromAll)
|
||||
{
|
||||
@ -1909,6 +1909,7 @@ void cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
|
||||
}
|
||||
target->AddSources(srcs);
|
||||
this->AddGlobalLinkInformation(lname, *target);
|
||||
return target;
|
||||
}
|
||||
|
||||
cmTarget* cmMakefile::AddExecutable(const char *exeName,
|
||||
|
@ -325,7 +325,7 @@ public:
|
||||
/**
|
||||
* Set the name of the library.
|
||||
*/
|
||||
void AddLibrary(const char *libname, cmTarget::TargetType type,
|
||||
cmTarget* AddLibrary(const char *libname, cmTarget::TargetType type,
|
||||
const std::vector<std::string> &srcs,
|
||||
bool excludeFromAll = false);
|
||||
|
||||
|
782
Source/cmQtAutomoc.cxx
Normal file
782
Source/cmQtAutomoc.cxx
Normal file
@ -0,0 +1,782 @@
|
||||
#include "cmGlobalGenerator.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
# include <cmsys/Terminal.h>
|
||||
|
||||
#include "cmQtAutomoc.h"
|
||||
|
||||
|
||||
cmQtAutomoc::cmQtAutomoc()
|
||||
:Verbose(cmsys::SystemTools::GetEnv("VERBOSE") != 0)
|
||||
,ColorOutput(true)
|
||||
,RunMocFailed(false)
|
||||
,GenerateAll(false)
|
||||
{
|
||||
|
||||
std::string colorEnv = "";
|
||||
cmsys::SystemTools::GetEnv("COLOR", colorEnv);
|
||||
if(!colorEnv.empty())
|
||||
{
|
||||
if(cmSystemTools::IsOn(colorEnv.c_str()))
|
||||
{
|
||||
this->ColorOutput = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->ColorOutput = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
|
||||
{
|
||||
cmMakefile* makefile = target->GetMakefile();
|
||||
const char* targetName = target->GetName();
|
||||
// don't do anything if there is no Qt4:
|
||||
std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
|
||||
if (qtMajorVersion != "4")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// create a custom target for running automoc at buildtime:
|
||||
std::string automocTargetName = targetName;
|
||||
automocTargetName += "_automoc";
|
||||
|
||||
std::string targetDir = makefile->GetCurrentOutputDirectory();
|
||||
targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
|
||||
targetDir += "/";
|
||||
targetDir += automocTargetName;
|
||||
targetDir += ".dir/";
|
||||
|
||||
cmCustomCommandLine currentLine;
|
||||
currentLine.push_back(makefile->GetCMakeInstance()->GetCMakeCommand());
|
||||
currentLine.push_back("-E");
|
||||
currentLine.push_back("cmake_automoc");
|
||||
currentLine.push_back(targetDir);
|
||||
|
||||
cmCustomCommandLines commandLines;
|
||||
commandLines.push_back(currentLine);
|
||||
|
||||
std::string workingDirectory = cmSystemTools::CollapseFullPath(
|
||||
"", makefile->GetCurrentOutputDirectory());
|
||||
|
||||
std::vector<std::string> depends;
|
||||
std::string automocComment = "Automoc for target ";
|
||||
automocComment += targetName;
|
||||
|
||||
makefile->AddUtilityCommand(automocTargetName.c_str(), true,
|
||||
workingDirectory.c_str(), depends,
|
||||
commandLines, false, automocComment.c_str());
|
||||
target->AddUtility(automocTargetName.c_str());
|
||||
|
||||
// configure a file to get all information to automoc at buildtime:
|
||||
std::string _moc_files;
|
||||
std::string _moc_headers;
|
||||
const char* sepFiles = "";
|
||||
const char* sepHeaders = "";
|
||||
|
||||
const std::vector<cmSourceFile*>& srcFiles = target->GetSourceFiles();
|
||||
|
||||
for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
|
||||
fileIt != srcFiles.end();
|
||||
++fileIt)
|
||||
{
|
||||
cmSourceFile* sf = *fileIt;
|
||||
std::string absFile = sf->GetFullPath();
|
||||
bool skip = cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC"));
|
||||
bool generated = cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"));
|
||||
|
||||
if ((skip==false) && (generated == false))
|
||||
{
|
||||
std::string ext = sf->GetExtension();
|
||||
cmSystemTools::FileFormat fileType = cmSystemTools::GetFileFormat(
|
||||
ext.c_str());
|
||||
if (fileType == cmSystemTools::CXX_FILE_FORMAT)
|
||||
{
|
||||
_moc_files += sepFiles;
|
||||
_moc_files += absFile;
|
||||
sepFiles = ";";
|
||||
}
|
||||
else if (fileType == cmSystemTools::HEADER_FILE_FORMAT)
|
||||
{
|
||||
_moc_headers += sepHeaders;
|
||||
_moc_headers += absFile;
|
||||
sepHeaders = ";";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string _moc_incs = makefile->GetProperty("INCLUDE_DIRECTORIES");
|
||||
std::string _moc_defs = makefile->GetProperty("DEFINITIONS");
|
||||
std::string _moc_compile_defs = makefile->GetProperty("COMPILE_DEFINITIONS");
|
||||
// forget the variables added here afterwards again:
|
||||
cmMakefile::ScopePushPop varScope(makefile);
|
||||
static_cast<void>(varScope);
|
||||
|
||||
makefile->AddDefinition("_moc_target_name", automocTargetName.c_str());
|
||||
makefile->AddDefinition("_moc_incs", _moc_incs.c_str());
|
||||
makefile->AddDefinition("_moc_defs", _moc_defs.c_str());
|
||||
makefile->AddDefinition("_moc_compile_defs", _moc_compile_defs.c_str());
|
||||
makefile->AddDefinition("_moc_files", _moc_files.c_str());
|
||||
makefile->AddDefinition("_moc_headers", _moc_headers.c_str());
|
||||
|
||||
const char* cmakeRoot = makefile->GetDefinition("CMAKE_ROOT");
|
||||
std::string inputFile = cmakeRoot;
|
||||
inputFile += "/Modules/AutomocInfo.cmake.in";
|
||||
std::string outputFile = targetDir;
|
||||
outputFile += "/AutomocInfo.cmake";
|
||||
makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(),
|
||||
false, true, false);
|
||||
|
||||
std::string mocCppFile = makefile->GetCurrentOutputDirectory();
|
||||
mocCppFile += "/";
|
||||
mocCppFile += automocTargetName;
|
||||
mocCppFile += ".cpp";
|
||||
cmSourceFile* mocCppSource = makefile->GetOrCreateSource(mocCppFile.c_str(),
|
||||
true);
|
||||
target->AddSourceFile(mocCppSource);
|
||||
|
||||
makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
|
||||
mocCppFile.c_str(), false);
|
||||
}
|
||||
|
||||
|
||||
bool cmQtAutomoc::Run(const char* targetDirectory)
|
||||
{
|
||||
cmake cm;
|
||||
cmGlobalGenerator* gg = this->CreateGlobalGenerator(&cm, targetDirectory);
|
||||
cmMakefile* makefile = gg->GetCurrentLocalGenerator()->GetMakefile();
|
||||
|
||||
this->ReadAutomocInfoFile(makefile, targetDirectory);
|
||||
this->ReadOldMocDefinitionsFile(makefile, targetDirectory);
|
||||
|
||||
this->Init();
|
||||
|
||||
if (this->QtMajorVersion == "4")
|
||||
{
|
||||
this->RunAutomocQt4();
|
||||
}
|
||||
|
||||
this->WriteOldMocDefinitionsFile(targetDirectory);
|
||||
|
||||
delete gg;
|
||||
gg = NULL;
|
||||
makefile = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
cmGlobalGenerator* cmQtAutomoc::CreateGlobalGenerator(cmake* cm,
|
||||
const char* targetDirectory)
|
||||
{
|
||||
cmGlobalGenerator* gg = new cmGlobalGenerator();
|
||||
gg->SetCMakeInstance(cm);
|
||||
|
||||
cmLocalGenerator* lg = gg->CreateLocalGenerator();
|
||||
lg->GetMakefile()->SetHomeOutputDirectory(targetDirectory);
|
||||
lg->GetMakefile()->SetStartOutputDirectory(targetDirectory);
|
||||
lg->GetMakefile()->SetHomeDirectory(targetDirectory);
|
||||
lg->GetMakefile()->SetStartDirectory(targetDirectory);
|
||||
gg->SetCurrentLocalGenerator(lg);
|
||||
|
||||
return gg;
|
||||
}
|
||||
|
||||
|
||||
bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile,
|
||||
const char* targetDirectory)
|
||||
{
|
||||
std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
|
||||
cmSystemTools::ConvertToUnixSlashes(filename);
|
||||
filename += "/AutomocInfo.cmake";
|
||||
|
||||
if (!makefile->ReadListFile(0, filename.c_str()))
|
||||
{
|
||||
cmSystemTools::Error("Error processing file:", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
this->QtMajorVersion = makefile->GetSafeDefinition("AM_QT_VERSION_MAJOR");
|
||||
this->Sources = makefile->GetSafeDefinition("AM_SOURCES");
|
||||
this->Headers = makefile->GetSafeDefinition("AM_HEADERS");
|
||||
this->IncludeProjectDirsBefore = makefile->IsOn(
|
||||
"AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
|
||||
this->Srcdir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_SOURCE_DIR");
|
||||
this->Builddir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR");
|
||||
this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE");
|
||||
this->MocCompileDefinitionsStr = makefile->GetSafeDefinition(
|
||||
"AM_MOC_COMPILE_DEFINITIONS");
|
||||
this->MocDefinitionsStr = makefile->GetSafeDefinition("AM_MOC_DEFINITIONS");
|
||||
this->MocIncludesStr = makefile->GetSafeDefinition("AM_MOC_INCLUDES");
|
||||
this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR");
|
||||
this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR");
|
||||
this->TargetName = makefile->GetSafeDefinition("AM_TARGET_NAME");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool cmQtAutomoc::ReadOldMocDefinitionsFile(cmMakefile* makefile,
|
||||
const char* targetDirectory)
|
||||
{
|
||||
std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
|
||||
cmSystemTools::ConvertToUnixSlashes(filename);
|
||||
filename += "/AutomocOldMocDefinitions.cmake";
|
||||
|
||||
if (makefile->ReadListFile(0, filename.c_str()))
|
||||
{
|
||||
this->OldMocDefinitionsStr =
|
||||
makefile->GetSafeDefinition("AM_OLD_MOC_DEFINITIONS");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void cmQtAutomoc::WriteOldMocDefinitionsFile(const char* targetDirectory)
|
||||
{
|
||||
std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
|
||||
cmSystemTools::ConvertToUnixSlashes(filename);
|
||||
filename += "/AutomocOldMocDefinitions.cmake";
|
||||
|
||||
std::fstream outfile;
|
||||
outfile.open(filename.c_str(),
|
||||
std::ios::out | std::ios::trunc);
|
||||
outfile << "set(AM_OLD_MOC_DEFINITIONS \""
|
||||
<< this->Join(this->MocDefinitions, ' ') << "\")\n";
|
||||
|
||||
outfile.close();
|
||||
}
|
||||
|
||||
|
||||
void cmQtAutomoc::Init()
|
||||
{
|
||||
this->OutMocCppFilename = this->Builddir;
|
||||
this->OutMocCppFilename += this->TargetName;
|
||||
this->OutMocCppFilename += ".cpp";
|
||||
|
||||
std::vector<std::string> cdefList;
|
||||
cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList);
|
||||
if (!cdefList.empty())
|
||||
{
|
||||
for(std::vector<std::string>::const_iterator it = cdefList.begin();
|
||||
it != cdefList.end();
|
||||
++it)
|
||||
{
|
||||
this->MocDefinitions.push_back("-D" + (*it));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string tmpMocDefs = this->MocDefinitionsStr;
|
||||
cmSystemTools::ReplaceString(tmpMocDefs, " ", ";");
|
||||
|
||||
std::vector<std::string> defList;
|
||||
cmSystemTools::ExpandListArgument(tmpMocDefs, defList);
|
||||
|
||||
for(std::vector<std::string>::const_iterator it = defList.begin();
|
||||
it != defList.end();
|
||||
++it)
|
||||
{
|
||||
if (this->StartsWith(*it, "-D"))
|
||||
{
|
||||
this->MocDefinitions.push_back(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> incPaths;
|
||||
cmSystemTools::ExpandListArgument(this->MocIncludesStr, incPaths);
|
||||
|
||||
std::set<std::string> frameworkPaths;
|
||||
for(std::vector<std::string>::const_iterator it = incPaths.begin();
|
||||
it != incPaths.end();
|
||||
++it)
|
||||
{
|
||||
const std::string &path = *it;
|
||||
this->MocIncludes.push_back("-I" + path);
|
||||
if (this->EndsWith(path, ".framework/Headers"))
|
||||
{
|
||||
// Go up twice to get to the framework root
|
||||
std::vector<std::string> pathComponents;
|
||||
cmsys::SystemTools::SplitPath(path.c_str(), pathComponents);
|
||||
std::string frameworkPath =cmsys::SystemTools::JoinPath(
|
||||
pathComponents.begin(), pathComponents.end() - 2);
|
||||
frameworkPaths.insert(frameworkPath);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
|
||||
it != frameworkPaths.end(); ++it)
|
||||
{
|
||||
this->MocIncludes.push_back("-F");
|
||||
this->MocIncludes.push_back(*it);
|
||||
}
|
||||
|
||||
|
||||
if (this->IncludeProjectDirsBefore)
|
||||
{
|
||||
const std::string &binDir = "-I" + this->ProjectBinaryDir;
|
||||
|
||||
const std::string srcDir = "-I" + this->ProjectSourceDir;
|
||||
|
||||
std::list<std::string> sortedMocIncludes;
|
||||
std::list<std::string>::iterator it = this->MocIncludes.begin();
|
||||
while (it != this->MocIncludes.end())
|
||||
{
|
||||
if (this->StartsWith(*it, binDir))
|
||||
{
|
||||
sortedMocIncludes.push_back(*it);
|
||||
it = this->MocIncludes.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
it = this->MocIncludes.begin();
|
||||
while (it != this->MocIncludes.end())
|
||||
{
|
||||
if (this->StartsWith(*it, srcDir))
|
||||
{
|
||||
sortedMocIncludes.push_back(*it);
|
||||
it = this->MocIncludes.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
sortedMocIncludes.insert(sortedMocIncludes.end(),
|
||||
this->MocIncludes.begin(), this->MocIncludes.end());
|
||||
this->MocIncludes = sortedMocIncludes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool cmQtAutomoc::RunAutomocQt4()
|
||||
{
|
||||
if (!cmsys::SystemTools::FileExists(this->OutMocCppFilename.c_str())
|
||||
|| (this->OldMocDefinitionsStr != this->Join(this->MocDefinitions, ' ')))
|
||||
{
|
||||
this->GenerateAll = true;
|
||||
}
|
||||
|
||||
// the program goes through all .cpp files to see which moc files are
|
||||
// included. It is not really interesting how the moc file is named, but
|
||||
// what file the moc is created from. Once a moc is included the same moc
|
||||
// may not be included in the _automoc.cpp file anymore. OTOH if there's a
|
||||
// header containing Q_OBJECT where no corresponding moc file is included
|
||||
// anywhere a moc_<filename>.cpp file is created and included in
|
||||
// the _automoc.cpp file.
|
||||
|
||||
// key = moc source filepath, value = moc output filepath
|
||||
std::map<std::string, std::string> includedMocs;
|
||||
// key = moc source filepath, value = moc output filename
|
||||
std::map<std::string, std::string> notIncludedMocs;
|
||||
|
||||
|
||||
std::vector<std::string> sourceFiles;
|
||||
cmSystemTools::ExpandListArgument(this->Sources, sourceFiles);
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = sourceFiles.begin();
|
||||
it != sourceFiles.end();
|
||||
++it)
|
||||
{
|
||||
const std::string &absFilename = *it;
|
||||
if (this->Verbose)
|
||||
{
|
||||
std::cout << "AUTOMOC: Checking " << absFilename << std::endl;
|
||||
}
|
||||
this->ParseCppFile(absFilename, includedMocs, notIncludedMocs);
|
||||
}
|
||||
|
||||
std::vector<std::string> headerFiles;
|
||||
cmSystemTools::ExpandListArgument(this->Headers, headerFiles);
|
||||
for (std::vector<std::string>::const_iterator it = headerFiles.begin();
|
||||
it != headerFiles.end();
|
||||
++it)
|
||||
{
|
||||
const std::string &absFilename = *it;
|
||||
if (this->Verbose)
|
||||
{
|
||||
std::cout << "AUTOMOC: Checking " << absFilename << std::endl;
|
||||
}
|
||||
if (includedMocs.find(absFilename) == includedMocs.end()
|
||||
&& notIncludedMocs.find(absFilename) == notIncludedMocs.end())
|
||||
{
|
||||
// if this header is not getting processed yet and is explicitly
|
||||
// mentioned for the automoc the moc is run unconditionally on the
|
||||
// header and the resulting file is included in the _automoc.cpp file
|
||||
// (unless there's a .cpp file later on that includes the moc from
|
||||
// this header)
|
||||
const std::string currentMoc = "moc_" + cmsys::SystemTools::
|
||||
GetFilenameWithoutLastExtension(absFilename) + ".cpp";
|
||||
notIncludedMocs[absFilename] = currentMoc;
|
||||
}
|
||||
}
|
||||
|
||||
// run moc on all the moc's that are #included in source files
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
it = includedMocs.begin();
|
||||
it != includedMocs.end();
|
||||
++it)
|
||||
{
|
||||
this->GenerateMoc(it->first, it->second);
|
||||
}
|
||||
|
||||
std::stringstream outStream(std::stringstream::out);
|
||||
outStream << "/* This file is autogenerated, do not edit*/\n";
|
||||
|
||||
bool automocCppChanged = false;
|
||||
if (notIncludedMocs.empty())
|
||||
{
|
||||
outStream << "enum some_compilers { need_more_than_nothing };\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// run moc on the remaining headers and include them in
|
||||
// the _automoc.cpp file
|
||||
for(std::map<std::string, std::string>::const_iterator
|
||||
it = notIncludedMocs.begin();
|
||||
it != notIncludedMocs.end();
|
||||
++it)
|
||||
{
|
||||
bool mocSuccess = this->GenerateMoc(it->first, it->second);
|
||||
if (mocSuccess)
|
||||
{
|
||||
automocCppChanged = true;
|
||||
}
|
||||
outStream << "#include \"" << it->second << "\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (this->RunMocFailed)
|
||||
{
|
||||
std::cerr << "returning failed.."<< std::endl;
|
||||
return false;
|
||||
}
|
||||
outStream.flush();
|
||||
std::string automocSource = outStream.str();
|
||||
if (!automocCppChanged)
|
||||
{
|
||||
// compare contents of the _automoc.cpp file
|
||||
const std::string oldContents = this->ReadAll(this->OutMocCppFilename);
|
||||
if (oldContents == automocSource)
|
||||
{
|
||||
// nothing changed: don't touch the _automoc.cpp file
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// source file that includes all remaining moc files (_automoc.cpp file)
|
||||
std::fstream outfile;
|
||||
outfile.open(this->OutMocCppFilename.c_str(),
|
||||
std::ios::out | std::ios::trunc);
|
||||
outfile << automocSource;
|
||||
outfile.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
|
||||
std::map<std::string, std::string>& includedMocs,
|
||||
std::map<std::string, std::string>& notIncludedMocs)
|
||||
{
|
||||
cmsys::RegularExpression mocIncludeRegExp(
|
||||
"[\n][ \t]*#[ \t]*include[ \t]+"
|
||||
"[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
|
||||
cmsys::RegularExpression qObjectRegExp("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
|
||||
std::list<std::string> headerExtensions;
|
||||
headerExtensions.push_back(".h");
|
||||
headerExtensions.push_back(".hpp");
|
||||
headerExtensions.push_back(".hxx");
|
||||
#if defined(_WIN32)
|
||||
// not case sensitive, don't add ".H"
|
||||
#elif defined(__APPLE__)
|
||||
// detect case-sensitive filesystem
|
||||
long caseSensitive = pathconf(this->Srcdir.c_str(), _PC_CASE_SENSITIVE);
|
||||
if (caseSensitive == 1)
|
||||
{
|
||||
headerExtensions.push_back(".H");
|
||||
}
|
||||
#else
|
||||
headerExtensions.push_back(".H");
|
||||
#endif
|
||||
|
||||
const std::string contentsString = this->ReadAll(absFilename);
|
||||
if (contentsString.empty())
|
||||
{
|
||||
std::cerr << "AUTOMOC: empty source file: " << absFilename << std::endl;
|
||||
return;
|
||||
}
|
||||
const std::string absPath = cmsys::SystemTools::GetFilenamePath(
|
||||
cmsys::SystemTools::GetRealPath(absFilename.c_str())) + '/';
|
||||
|
||||
std::string::size_type matchOffset = 0;
|
||||
if (!mocIncludeRegExp.find(contentsString.c_str()))
|
||||
{
|
||||
// no moc #include, look whether we need to create a moc from
|
||||
// the .h nevertheless
|
||||
const std::string basename =
|
||||
cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
|
||||
for(std::list<std::string>::const_iterator ext = headerExtensions.begin();
|
||||
ext != headerExtensions.end();
|
||||
++ext)
|
||||
{
|
||||
const std::string headername = absPath + basename + (*ext);
|
||||
if (cmsys::SystemTools::FileExists(headername.c_str())
|
||||
&& includedMocs.find(headername) == includedMocs.end()
|
||||
&& notIncludedMocs.find(headername) == notIncludedMocs.end())
|
||||
{
|
||||
const std::string currentMoc = "moc_" + basename + ".cpp";
|
||||
const std::string contents = this->ReadAll(headername);
|
||||
if (qObjectRegExp.find(contents))
|
||||
{
|
||||
//std::cout << "header contains Q_OBJECT macro";
|
||||
notIncludedMocs[headername] = currentMoc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(std::list<std::string>::const_iterator ext = headerExtensions.begin();
|
||||
ext != headerExtensions.end();
|
||||
++ext)
|
||||
{
|
||||
const std::string privateHeaderName = absPath+basename+"_p"+(*ext);
|
||||
if (cmsys::SystemTools::FileExists(privateHeaderName.c_str())
|
||||
&& includedMocs.find(privateHeaderName) == includedMocs.end()
|
||||
&& notIncludedMocs.find(privateHeaderName) == notIncludedMocs.end())
|
||||
{
|
||||
const std::string currentMoc = "moc_" + basename + "_p.cpp";
|
||||
const std::string contents = this->ReadAll(privateHeaderName);
|
||||
if (qObjectRegExp.find(contents))
|
||||
{
|
||||
//std::cout << "header contains Q_OBJECT macro";
|
||||
notIncludedMocs[privateHeaderName] = currentMoc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// for every moc include in the file
|
||||
do
|
||||
{
|
||||
const std::string currentMoc = mocIncludeRegExp.match(1);
|
||||
//std::cout << "found moc include: " << currentMoc << std::endl;
|
||||
|
||||
std::string basename = cmsys::SystemTools::
|
||||
GetFilenameWithoutLastExtension(currentMoc);
|
||||
const bool moc_style = this->StartsWith(basename, "moc_");
|
||||
|
||||
// If the moc include is of the moc_foo.cpp style we expect
|
||||
// the Q_OBJECT class declaration in a header file.
|
||||
// If the moc include is of the foo.moc style we need to look for
|
||||
// a Q_OBJECT macro in the current source file, if it contains the
|
||||
// macro we generate the moc file from the source file, else from the
|
||||
// header.
|
||||
// Q_OBJECT
|
||||
if (moc_style || !qObjectRegExp.find(contentsString))
|
||||
{
|
||||
if (moc_style)
|
||||
{
|
||||
// basename should be the part of the moc filename used for
|
||||
// finding the correct header, so we need to remove the moc_ part
|
||||
basename = basename.substr(4);
|
||||
}
|
||||
|
||||
bool headerFound = false;
|
||||
for(std::list<std::string>::const_iterator ext =
|
||||
headerExtensions.begin();
|
||||
ext != headerExtensions.end();
|
||||
++ext)
|
||||
{
|
||||
const std::string &sourceFilePath = absPath + basename + (*ext);
|
||||
if (cmsys::SystemTools::FileExists(sourceFilePath.c_str()))
|
||||
{
|
||||
headerFound = true;
|
||||
includedMocs[sourceFilePath] = currentMoc;
|
||||
notIncludedMocs.erase(sourceFilePath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!headerFound)
|
||||
{
|
||||
// the moc file is in a subdir => look for the header in the
|
||||
// same subdir
|
||||
if (currentMoc.find_first_of('/') != std::string::npos)
|
||||
{
|
||||
const std::string &filepath = absPath
|
||||
+ cmsys::SystemTools::GetFilenamePath(currentMoc)
|
||||
+ '/' + basename;
|
||||
|
||||
for(std::list<std::string>::const_iterator ext =
|
||||
headerExtensions.begin();
|
||||
ext != headerExtensions.end();
|
||||
++ext)
|
||||
{
|
||||
const std::string &sourceFilePath = filepath + (*ext);
|
||||
if (cmsys::SystemTools::FileExists(sourceFilePath.c_str()))
|
||||
{
|
||||
headerFound = true;
|
||||
includedMocs[sourceFilePath] = currentMoc;
|
||||
notIncludedMocs.erase(sourceFilePath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!headerFound)
|
||||
{
|
||||
std::cerr << "AUTOMOC: The file \"" << absFilename
|
||||
<< "\" includes the moc file \"" << currentMoc
|
||||
<< "\", but neither \"" << absPath << basename
|
||||
<< '{' << this->Join(headerExtensions, ',')
|
||||
<< "}\" nor \"" << filepath << '{'
|
||||
<< this->Join(headerExtensions, ',') << '}'
|
||||
<< "\" exist." << std::endl;
|
||||
::exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "AUTOMOC: The file \"" << absFilename
|
||||
<< "\" includes the moc file \"" << currentMoc
|
||||
<< "\", but \"" << absPath << basename << '{'
|
||||
<< this->Join(headerExtensions, ',') << '}'
|
||||
<< "\" does not exist." << std::endl;
|
||||
::exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
includedMocs[absFilename] = currentMoc;
|
||||
notIncludedMocs.erase(absFilename);
|
||||
}
|
||||
matchOffset += mocIncludeRegExp.end();
|
||||
} while(mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool cmQtAutomoc::GenerateMoc(const std::string& sourceFile,
|
||||
const std::string& mocFileName)
|
||||
{
|
||||
const std::string mocFilePath = this->Builddir + mocFileName;
|
||||
int sourceNewerThanMoc = 0;
|
||||
bool success = cmsys::SystemTools::FileTimeCompare(sourceFile.c_str(),
|
||||
mocFilePath.c_str(),
|
||||
&sourceNewerThanMoc);
|
||||
if (this->GenerateAll || !success || sourceNewerThanMoc >= 0)
|
||||
{
|
||||
// make sure the directory for the resulting moc file exists
|
||||
std::string mocDir = mocFilePath.substr(0, mocFilePath.rfind('/'));
|
||||
if (!cmsys::SystemTools::FileExists(mocDir.c_str(), false))
|
||||
{
|
||||
cmsys::SystemTools::MakeDirectory(mocDir.c_str());
|
||||
}
|
||||
|
||||
std::string msg = "Generating ";
|
||||
msg += mocFileName;
|
||||
cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue
|
||||
|cmsysTerminal_Color_ForegroundBold,
|
||||
msg.c_str(), true, this->ColorOutput);
|
||||
|
||||
std::vector<cmStdString> command;
|
||||
command.push_back(this->MocExecutable);
|
||||
for (std::list<std::string>::const_iterator it = this->MocIncludes.begin();
|
||||
it != this->MocIncludes.end();
|
||||
++it)
|
||||
{
|
||||
command.push_back(*it);
|
||||
}
|
||||
for(std::list<std::string>::const_iterator it=this->MocDefinitions.begin();
|
||||
it != this->MocDefinitions.end();
|
||||
++it)
|
||||
{
|
||||
command.push_back(*it);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
command.push_back("-DWIN32");
|
||||
#endif
|
||||
command.push_back("-o");
|
||||
command.push_back(mocFilePath);
|
||||
command.push_back(sourceFile);
|
||||
|
||||
if (this->Verbose)
|
||||
{
|
||||
for(std::vector<cmStdString>::const_iterator cmdIt = command.begin();
|
||||
cmdIt != command.end();
|
||||
++cmdIt)
|
||||
{
|
||||
std::cout << *cmdIt << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::string output;
|
||||
int retVal = 0;
|
||||
bool result = cmSystemTools::RunSingleCommand(command, &output, &retVal);
|
||||
if (!result || retVal)
|
||||
{
|
||||
std::cerr << "AUTOMOC: process for " << mocFilePath << " failed:\n"
|
||||
<< output << std::endl;
|
||||
this->RunMocFailed = true;
|
||||
cmSystemTools::RemoveFile(mocFilePath.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::string cmQtAutomoc::Join(const std::list<std::string>& lst,char separator)
|
||||
{
|
||||
if (lst.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string result;
|
||||
for (std::list<std::string>::const_iterator it = lst.begin();
|
||||
it != lst.end();
|
||||
++it)
|
||||
{
|
||||
result += (*it) + separator;
|
||||
}
|
||||
result.erase(result.end() - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool cmQtAutomoc::StartsWith(const std::string& str, const std::string& with)
|
||||
{
|
||||
return (str.substr(0, with.length()) == with);
|
||||
}
|
||||
|
||||
|
||||
bool cmQtAutomoc::EndsWith(const std::string& str, const std::string& with)
|
||||
{
|
||||
if (with.length() > (str.length()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return (str.substr(str.length() - with.length(), with.length()) == with);
|
||||
}
|
||||
|
||||
|
||||
std::string cmQtAutomoc::ReadAll(const std::string& filename)
|
||||
{
|
||||
std::ifstream file(filename.c_str());
|
||||
std::stringstream stream;
|
||||
stream << file.rdbuf();
|
||||
file.close();
|
||||
return stream.str();
|
||||
}
|
66
Source/cmQtAutomoc.h
Normal file
66
Source/cmQtAutomoc.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef cmQtAutomoc_h
|
||||
#define cmQtAutomoc_h
|
||||
|
||||
class cmGlobalGenerator;
|
||||
class cmMakefile;
|
||||
|
||||
class cmQtAutomoc
|
||||
{
|
||||
public:
|
||||
cmQtAutomoc();
|
||||
bool Run(const char* targetDirectory);
|
||||
|
||||
void SetupAutomocTarget(cmTarget* target);
|
||||
|
||||
private:
|
||||
cmGlobalGenerator* CreateGlobalGenerator(cmake* cm,
|
||||
const char* targetDirectory);
|
||||
|
||||
bool ReadAutomocInfoFile(cmMakefile* makefile,
|
||||
const char* targetDirectory);
|
||||
bool ReadOldMocDefinitionsFile(cmMakefile* makefile,
|
||||
const char* targetDirectory);
|
||||
void WriteOldMocDefinitionsFile(const char* targetDirectory);
|
||||
|
||||
bool RunAutomocQt4();
|
||||
bool GenerateMoc(const std::string& sourceFile,
|
||||
const std::string& mocFileName);
|
||||
void ParseCppFile(const std::string& absFilename,
|
||||
std::map<std::string, std::string>& includedMocs,
|
||||
std::map<std::string, std::string>& notIncludedMocs);
|
||||
|
||||
void Init();
|
||||
|
||||
std::string Join(const std::list<std::string>& lst, char separator);
|
||||
bool EndsWith(const std::string& str, const std::string& with);
|
||||
bool StartsWith(const std::string& str, const std::string& with);
|
||||
std::string ReadAll(const std::string& filename);
|
||||
|
||||
std::string QtMajorVersion;
|
||||
std::string Sources;
|
||||
std::string Headers;
|
||||
bool IncludeProjectDirsBefore;
|
||||
std::string Srcdir;
|
||||
std::string Builddir;
|
||||
std::string MocExecutable;
|
||||
std::string MocCompileDefinitionsStr;
|
||||
std::string MocDefinitionsStr;
|
||||
std::string MocIncludesStr;
|
||||
std::string ProjectBinaryDir;
|
||||
std::string ProjectSourceDir;
|
||||
std::string TargetName;
|
||||
|
||||
std::string OldMocDefinitionsStr;
|
||||
|
||||
std::string OutMocCppFilename;
|
||||
std::list<std::string> MocIncludes;
|
||||
std::list<std::string> MocDefinitions;
|
||||
|
||||
bool Verbose;
|
||||
bool ColorOutput;
|
||||
bool RunMocFailed;
|
||||
bool GenerateAll;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -114,6 +114,28 @@ cmTarget::cmTarget()
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::DefineProperties(cmake *cm)
|
||||
{
|
||||
cm->DefineProperty
|
||||
("AUTOMOC", cmProperty::TARGET,
|
||||
"Should the target be processed with automoc (for Qt projects).",
|
||||
"AUTOMOC is a boolean specifying whether CMake will handle "
|
||||
"the Qt moc preprocessor automatically, i.e. without having to use "
|
||||
"the QT4_WRAP_CPP() macro. Currently Qt4 is supported. "
|
||||
"When this property is set to TRUE, CMake will scan the source files "
|
||||
"at build time and invoke moc accordingly. "
|
||||
"If an #include statement like #include \"moc_foo.cpp\" is found, "
|
||||
"the Q_OBJECT class declaration is expected in the header, and moc is "
|
||||
"run on the header file. "
|
||||
"If an #include statement like #include \"foo.moc\" is found, "
|
||||
"then a Q_OBJECT is expected in the current source file and moc "
|
||||
"is run on the file itself. "
|
||||
"Additionally, all header files are parsed for Q_OBJECT macros, "
|
||||
"and if found, moc is also executed on those files. The resulting "
|
||||
"moc files, which are not included as shown above in any of the source "
|
||||
"files are included in a generated <targetname>_automoc.cpp file, "
|
||||
"which is compiled as part of the target."
|
||||
"This property is initialized by the value of the variable "
|
||||
"CMAKE_AUTOMOC if it is set when a target is created.");
|
||||
|
||||
cm->DefineProperty
|
||||
("BUILD_WITH_INSTALL_RPATH", cmProperty::TARGET,
|
||||
"Should build tree targets have install tree rpaths.",
|
||||
@ -1118,6 +1140,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
|
||||
this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
|
||||
this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
|
||||
this->SetPropertyDefault("OSX_ARCHITECTURES", 0);
|
||||
this->SetPropertyDefault("AUTOMOC", 0);
|
||||
|
||||
// Collect the set of configuration types.
|
||||
std::vector<std::string> configNames;
|
||||
@ -1420,7 +1443,7 @@ bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
|
||||
// the fact that the name matched a target was just a coincidence.
|
||||
if(cmSystemTools::FileIsFullPath(dep.c_str()))
|
||||
{
|
||||
if(t->GetType() >= cmTarget::EXECUTABLE &&
|
||||
if(t->GetType() >= cmTarget::EXECUTABLE &&
|
||||
t->GetType() <= cmTarget::MODULE_LIBRARY)
|
||||
{
|
||||
// This is really only for compatibility so we do not need to
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "cmCommand.h"
|
||||
#include "cmFileTimeComparison.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmQtAutomoc.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmVersion.h"
|
||||
#include "cmTest.h"
|
||||
@ -1572,6 +1573,12 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
|
||||
{
|
||||
return cmake::ExecuteEchoColor(args);
|
||||
}
|
||||
else if (args[1] == "cmake_automoc")
|
||||
{
|
||||
cmQtAutomoc automoc;
|
||||
automoc.Run(args[2].c_str());
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Tar files
|
||||
@ -2919,6 +2926,13 @@ const char* cmake::GetCPackCommand()
|
||||
return this->CPackCommand.c_str();
|
||||
}
|
||||
|
||||
|
||||
const char* cmake::GetCMakeCommand()
|
||||
{
|
||||
return this->CMakeCommand.c_str();
|
||||
}
|
||||
|
||||
|
||||
void cmake::MarkCliAsUsed(const std::string& variable)
|
||||
{
|
||||
this->UsedCliVariables[variable] = true;
|
||||
|
@ -301,6 +301,7 @@ class cmake
|
||||
*/
|
||||
const char* GetCTestCommand();
|
||||
const char* GetCPackCommand();
|
||||
const char* GetCMakeCommand();
|
||||
|
||||
// Do we want debug output during the cmake run.
|
||||
bool GetDebugOutput() { return this->DebugOutput; }
|
||||
|
@ -845,6 +845,45 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
|
||||
)
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Environment")
|
||||
|
||||
IF(NOT QT4_FOUND)
|
||||
FIND_PACKAGE(Qt4)
|
||||
ENDIF(NOT QT4_FOUND)
|
||||
|
||||
IF(QT4_FOUND)
|
||||
# test whether the Qt4 which has been found works, on some machines
|
||||
# which run nightly builds there were errors like "wrong file format"
|
||||
# for libQtCore.so. So first check it works, and only if it does add
|
||||
# the automoc test.
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
SET(_save_CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES}")
|
||||
SET(_save_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
|
||||
|
||||
SET(CMAKE_REQUIRED_INCLUDES ${QT_INCLUDES})
|
||||
SET(CMAKE_REQUIRED_LIBRARIES ${QT_QTCORE_LIBRARIES})
|
||||
|
||||
CHECK_CXX_SOURCE_COMPILES("#include <QCoreApplication>\n int main() {return (qApp == 0 ? 0 : 1); }\n"
|
||||
QT4_WORKS_FOR_AUTOMOC_TEST)
|
||||
|
||||
SET(CMAKE_REQUIRED_INCLUDES "${_save_CMAKE_REQUIRED_INCLUDES}")
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "${_save_CMAKE_REQUIRED_LIBRARIES}")
|
||||
|
||||
IF(QT4_WORKS_FOR_AUTOMOC_TEST)
|
||||
ADD_TEST(QtAutomoc ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/QtAutomoc"
|
||||
"${CMake_BINARY_DIR}/Tests/QtAutomoc"
|
||||
--build-generator ${CMAKE_TEST_GENERATOR}
|
||||
--build-project QtAutomoc
|
||||
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
|
||||
--build-exe-dir "${CMake_BINARY_DIR}/Tests/QtAutomoc"
|
||||
--force-new-ctest-process
|
||||
--build-options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
|
||||
--test-command ${CMAKE_CTEST_COMMAND} -V
|
||||
)
|
||||
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomoc")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
ADD_TEST(ExternalProject ${CMAKE_CTEST_COMMAND}
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/ExternalProject"
|
||||
|
20
Tests/QtAutomoc/CMakeLists.txt
Normal file
20
Tests/QtAutomoc/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(QtAutomoc)
|
||||
|
||||
find_package(Qt4 REQUIRED)
|
||||
|
||||
include(UseQt4)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_definitions(-DFOO)
|
||||
|
||||
# create an executable and a library target, both requiring automoc:
|
||||
add_library(codeeditorLib STATIC codeeditor.cpp)
|
||||
|
||||
add_executable(foo main.cpp calwidget.cpp )
|
||||
|
||||
set_target_properties(foo codeeditorLib PROPERTIES AUTOMOC TRUE)
|
||||
|
||||
target_link_libraries(foo codeeditorLib ${QT_LIBRARIES} )
|
424
Tests/QtAutomoc/calwidget.cpp
Normal file
424
Tests/QtAutomoc/calwidget.cpp
Normal file
@ -0,0 +1,424 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
#include "calwidget.h"
|
||||
|
||||
Window::Window()
|
||||
{
|
||||
createPreviewGroupBox();
|
||||
createGeneralOptionsGroupBox();
|
||||
createDatesGroupBox();
|
||||
createTextFormatsGroupBox();
|
||||
|
||||
QGridLayout *layout = new QGridLayout;
|
||||
layout->addWidget(previewGroupBox, 0, 0);
|
||||
layout->addWidget(generalOptionsGroupBox, 0, 1);
|
||||
layout->addWidget(datesGroupBox, 1, 0);
|
||||
layout->addWidget(textFormatsGroupBox, 1, 1);
|
||||
layout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
setLayout(layout);
|
||||
|
||||
previewLayout->setRowMinimumHeight(0, calendar->sizeHint().height());
|
||||
previewLayout->setColumnMinimumWidth(0, calendar->sizeHint().width());
|
||||
|
||||
setWindowTitle(tr("Calendar Widget"));
|
||||
}
|
||||
|
||||
void Window::localeChanged(int index)
|
||||
{
|
||||
calendar->setLocale(localeCombo->itemData(index).toLocale());
|
||||
}
|
||||
|
||||
void Window::firstDayChanged(int index)
|
||||
{
|
||||
calendar->setFirstDayOfWeek(Qt::DayOfWeek(
|
||||
firstDayCombo->itemData(index).toInt()));
|
||||
}
|
||||
|
||||
void Window::selectionModeChanged(int index)
|
||||
{
|
||||
calendar->setSelectionMode(QCalendarWidget::SelectionMode(
|
||||
selectionModeCombo->itemData(index).toInt()));
|
||||
}
|
||||
|
||||
void Window::horizontalHeaderChanged(int index)
|
||||
{
|
||||
calendar->setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat(
|
||||
horizontalHeaderCombo->itemData(index).toInt()));
|
||||
}
|
||||
|
||||
void Window::verticalHeaderChanged(int index)
|
||||
{
|
||||
calendar->setVerticalHeaderFormat(QCalendarWidget::VerticalHeaderFormat(
|
||||
verticalHeaderCombo->itemData(index).toInt()));
|
||||
}
|
||||
|
||||
void Window::selectedDateChanged()
|
||||
{
|
||||
currentDateEdit->setDate(calendar->selectedDate());
|
||||
}
|
||||
|
||||
void Window::minimumDateChanged(const QDate &date)
|
||||
{
|
||||
calendar->setMinimumDate(date);
|
||||
maximumDateEdit->setDate(calendar->maximumDate());
|
||||
}
|
||||
|
||||
void Window::maximumDateChanged(const QDate &date)
|
||||
{
|
||||
calendar->setMaximumDate(date);
|
||||
minimumDateEdit->setDate(calendar->minimumDate());
|
||||
}
|
||||
|
||||
void Window::weekdayFormatChanged()
|
||||
{
|
||||
QTextCharFormat format;
|
||||
|
||||
format.setForeground(qvariant_cast<QColor>(
|
||||
weekdayColorCombo->itemData(weekdayColorCombo->currentIndex())));
|
||||
calendar->setWeekdayTextFormat(Qt::Monday, format);
|
||||
calendar->setWeekdayTextFormat(Qt::Tuesday, format);
|
||||
calendar->setWeekdayTextFormat(Qt::Wednesday, format);
|
||||
calendar->setWeekdayTextFormat(Qt::Thursday, format);
|
||||
calendar->setWeekdayTextFormat(Qt::Friday, format);
|
||||
}
|
||||
|
||||
void Window::weekendFormatChanged()
|
||||
{
|
||||
QTextCharFormat format;
|
||||
|
||||
format.setForeground(qvariant_cast<QColor>(
|
||||
weekendColorCombo->itemData(weekendColorCombo->currentIndex())));
|
||||
calendar->setWeekdayTextFormat(Qt::Saturday, format);
|
||||
calendar->setWeekdayTextFormat(Qt::Sunday, format);
|
||||
}
|
||||
|
||||
void Window::reformatHeaders()
|
||||
{
|
||||
QString text = headerTextFormatCombo->currentText();
|
||||
QTextCharFormat format;
|
||||
|
||||
if (text == tr("Bold")) {
|
||||
format.setFontWeight(QFont::Bold);
|
||||
} else if (text == tr("Italic")) {
|
||||
format.setFontItalic(true);
|
||||
} else if (text == tr("Green")) {
|
||||
format.setForeground(Qt::green);
|
||||
}
|
||||
calendar->setHeaderTextFormat(format);
|
||||
}
|
||||
|
||||
void Window::reformatCalendarPage()
|
||||
{
|
||||
if (firstFridayCheckBox->isChecked()) {
|
||||
QDate firstFriday(calendar->yearShown(), calendar->monthShown(), 1);
|
||||
while (firstFriday.dayOfWeek() != Qt::Friday)
|
||||
firstFriday = firstFriday.addDays(1);
|
||||
QTextCharFormat firstFridayFormat;
|
||||
firstFridayFormat.setForeground(Qt::blue);
|
||||
calendar->setDateTextFormat(firstFriday, firstFridayFormat);
|
||||
}
|
||||
|
||||
//May First in Red takes precedence
|
||||
if (mayFirstCheckBox->isChecked()) {
|
||||
const QDate mayFirst(calendar->yearShown(), 5, 1);
|
||||
QTextCharFormat mayFirstFormat;
|
||||
mayFirstFormat.setForeground(Qt::red);
|
||||
calendar->setDateTextFormat(mayFirst, mayFirstFormat);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::createPreviewGroupBox()
|
||||
{
|
||||
previewGroupBox = new QGroupBox(tr("Preview"));
|
||||
|
||||
calendar = new QCalendarWidget;
|
||||
calendar->setMinimumDate(QDate(1900, 1, 1));
|
||||
calendar->setMaximumDate(QDate(3000, 1, 1));
|
||||
calendar->setGridVisible(true);
|
||||
|
||||
connect(calendar, SIGNAL(currentPageChanged(int,int)),
|
||||
this, SLOT(reformatCalendarPage()));
|
||||
|
||||
previewLayout = new QGridLayout;
|
||||
previewLayout->addWidget(calendar, 0, 0, Qt::AlignCenter);
|
||||
previewGroupBox->setLayout(previewLayout);
|
||||
}
|
||||
|
||||
void Window::createGeneralOptionsGroupBox()
|
||||
{
|
||||
generalOptionsGroupBox = new QGroupBox(tr("General Options"));
|
||||
|
||||
localeCombo = new QComboBox;
|
||||
int curLocaleIndex = -1;
|
||||
int index = 0;
|
||||
for (int _lang = QLocale::C; _lang <= QLocale::LastLanguage; ++_lang) {
|
||||
QLocale::Language lang = static_cast<QLocale::Language>(_lang);
|
||||
QList<QLocale::Country> countries = QLocale::countriesForLanguage(lang);
|
||||
for (int i = 0; i < countries.count(); ++i) {
|
||||
QLocale::Country country = countries.at(i);
|
||||
QString label = QLocale::languageToString(lang);
|
||||
label += QLatin1Char('/');
|
||||
label += QLocale::countryToString(country);
|
||||
QLocale locale(lang, country);
|
||||
if (this->locale().language() == lang && this->locale().country() == country)
|
||||
curLocaleIndex = index;
|
||||
localeCombo->addItem(label, locale);
|
||||
++index;
|
||||
}
|
||||
}
|
||||
if (curLocaleIndex != -1)
|
||||
localeCombo->setCurrentIndex(curLocaleIndex);
|
||||
localeLabel = new QLabel(tr("&Locale"));
|
||||
localeLabel->setBuddy(localeCombo);
|
||||
|
||||
firstDayCombo = new QComboBox;
|
||||
firstDayCombo->addItem(tr("Sunday"), Qt::Sunday);
|
||||
firstDayCombo->addItem(tr("Monday"), Qt::Monday);
|
||||
firstDayCombo->addItem(tr("Tuesday"), Qt::Tuesday);
|
||||
firstDayCombo->addItem(tr("Wednesday"), Qt::Wednesday);
|
||||
firstDayCombo->addItem(tr("Thursday"), Qt::Thursday);
|
||||
firstDayCombo->addItem(tr("Friday"), Qt::Friday);
|
||||
firstDayCombo->addItem(tr("Saturday"), Qt::Saturday);
|
||||
|
||||
firstDayLabel = new QLabel(tr("Wee&k starts on:"));
|
||||
firstDayLabel->setBuddy(firstDayCombo);
|
||||
|
||||
selectionModeCombo = new QComboBox;
|
||||
selectionModeCombo->addItem(tr("Single selection"),
|
||||
QCalendarWidget::SingleSelection);
|
||||
selectionModeCombo->addItem(tr("None"), QCalendarWidget::NoSelection);
|
||||
|
||||
selectionModeLabel = new QLabel(tr("&Selection mode:"));
|
||||
selectionModeLabel->setBuddy(selectionModeCombo);
|
||||
|
||||
gridCheckBox = new QCheckBox(tr("&Grid"));
|
||||
gridCheckBox->setChecked(calendar->isGridVisible());
|
||||
|
||||
navigationCheckBox = new QCheckBox(tr("&Navigation bar"));
|
||||
navigationCheckBox->setChecked(true);
|
||||
|
||||
horizontalHeaderCombo = new QComboBox;
|
||||
horizontalHeaderCombo->addItem(tr("Single letter day names"),
|
||||
QCalendarWidget::SingleLetterDayNames);
|
||||
horizontalHeaderCombo->addItem(tr("Short day names"),
|
||||
QCalendarWidget::ShortDayNames);
|
||||
horizontalHeaderCombo->addItem(tr("None"),
|
||||
QCalendarWidget::NoHorizontalHeader);
|
||||
horizontalHeaderCombo->setCurrentIndex(1);
|
||||
|
||||
horizontalHeaderLabel = new QLabel(tr("&Horizontal header:"));
|
||||
horizontalHeaderLabel->setBuddy(horizontalHeaderCombo);
|
||||
|
||||
verticalHeaderCombo = new QComboBox;
|
||||
verticalHeaderCombo->addItem(tr("ISO week numbers"),
|
||||
QCalendarWidget::ISOWeekNumbers);
|
||||
verticalHeaderCombo->addItem(tr("None"), QCalendarWidget::NoVerticalHeader);
|
||||
|
||||
verticalHeaderLabel = new QLabel(tr("&Vertical header:"));
|
||||
verticalHeaderLabel->setBuddy(verticalHeaderCombo);
|
||||
|
||||
connect(localeCombo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(localeChanged(int)));
|
||||
connect(firstDayCombo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(firstDayChanged(int)));
|
||||
connect(selectionModeCombo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(selectionModeChanged(int)));
|
||||
connect(gridCheckBox, SIGNAL(toggled(bool)),
|
||||
calendar, SLOT(setGridVisible(bool)));
|
||||
connect(navigationCheckBox, SIGNAL(toggled(bool)),
|
||||
calendar, SLOT(setNavigationBarVisible(bool)));
|
||||
connect(horizontalHeaderCombo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(horizontalHeaderChanged(int)));
|
||||
connect(verticalHeaderCombo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(verticalHeaderChanged(int)));
|
||||
|
||||
QHBoxLayout *checkBoxLayout = new QHBoxLayout;
|
||||
checkBoxLayout->addWidget(gridCheckBox);
|
||||
checkBoxLayout->addStretch();
|
||||
checkBoxLayout->addWidget(navigationCheckBox);
|
||||
|
||||
QGridLayout *outerLayout = new QGridLayout;
|
||||
outerLayout->addWidget(localeLabel, 0, 0);
|
||||
outerLayout->addWidget(localeCombo, 0, 1);
|
||||
outerLayout->addWidget(firstDayLabel, 1, 0);
|
||||
outerLayout->addWidget(firstDayCombo, 1, 1);
|
||||
outerLayout->addWidget(selectionModeLabel, 2, 0);
|
||||
outerLayout->addWidget(selectionModeCombo, 2, 1);
|
||||
outerLayout->addLayout(checkBoxLayout, 3, 0, 1, 2);
|
||||
outerLayout->addWidget(horizontalHeaderLabel, 4, 0);
|
||||
outerLayout->addWidget(horizontalHeaderCombo, 4, 1);
|
||||
outerLayout->addWidget(verticalHeaderLabel, 5, 0);
|
||||
outerLayout->addWidget(verticalHeaderCombo, 5, 1);
|
||||
generalOptionsGroupBox->setLayout(outerLayout);
|
||||
|
||||
firstDayChanged(firstDayCombo->currentIndex());
|
||||
selectionModeChanged(selectionModeCombo->currentIndex());
|
||||
horizontalHeaderChanged(horizontalHeaderCombo->currentIndex());
|
||||
verticalHeaderChanged(verticalHeaderCombo->currentIndex());
|
||||
}
|
||||
|
||||
void Window::createDatesGroupBox()
|
||||
{
|
||||
datesGroupBox = new QGroupBox(tr("Dates"));
|
||||
|
||||
minimumDateEdit = new QDateEdit;
|
||||
minimumDateEdit->setDisplayFormat("MMM d yyyy");
|
||||
minimumDateEdit->setDateRange(calendar->minimumDate(),
|
||||
calendar->maximumDate());
|
||||
minimumDateEdit->setDate(calendar->minimumDate());
|
||||
|
||||
minimumDateLabel = new QLabel(tr("&Minimum Date:"));
|
||||
minimumDateLabel->setBuddy(minimumDateEdit);
|
||||
|
||||
currentDateEdit = new QDateEdit;
|
||||
currentDateEdit->setDisplayFormat("MMM d yyyy");
|
||||
currentDateEdit->setDate(calendar->selectedDate());
|
||||
currentDateEdit->setDateRange(calendar->minimumDate(),
|
||||
calendar->maximumDate());
|
||||
|
||||
currentDateLabel = new QLabel(tr("&Current Date:"));
|
||||
currentDateLabel->setBuddy(currentDateEdit);
|
||||
|
||||
maximumDateEdit = new QDateEdit;
|
||||
maximumDateEdit->setDisplayFormat("MMM d yyyy");
|
||||
maximumDateEdit->setDateRange(calendar->minimumDate(),
|
||||
calendar->maximumDate());
|
||||
maximumDateEdit->setDate(calendar->maximumDate());
|
||||
|
||||
maximumDateLabel = new QLabel(tr("Ma&ximum Date:"));
|
||||
maximumDateLabel->setBuddy(maximumDateEdit);
|
||||
|
||||
connect(currentDateEdit, SIGNAL(dateChanged(QDate)),
|
||||
calendar, SLOT(setSelectedDate(QDate)));
|
||||
connect(calendar, SIGNAL(selectionChanged()),
|
||||
this, SLOT(selectedDateChanged()));
|
||||
connect(minimumDateEdit, SIGNAL(dateChanged(QDate)),
|
||||
this, SLOT(minimumDateChanged(QDate)));
|
||||
connect(maximumDateEdit, SIGNAL(dateChanged(QDate)),
|
||||
this, SLOT(maximumDateChanged(QDate)));
|
||||
|
||||
QGridLayout *dateBoxLayout = new QGridLayout;
|
||||
dateBoxLayout->addWidget(currentDateLabel, 1, 0);
|
||||
dateBoxLayout->addWidget(currentDateEdit, 1, 1);
|
||||
dateBoxLayout->addWidget(minimumDateLabel, 0, 0);
|
||||
dateBoxLayout->addWidget(minimumDateEdit, 0, 1);
|
||||
dateBoxLayout->addWidget(maximumDateLabel, 2, 0);
|
||||
dateBoxLayout->addWidget(maximumDateEdit, 2, 1);
|
||||
dateBoxLayout->setRowStretch(3, 1);
|
||||
|
||||
datesGroupBox->setLayout(dateBoxLayout);
|
||||
}
|
||||
|
||||
void Window::createTextFormatsGroupBox()
|
||||
{
|
||||
textFormatsGroupBox = new QGroupBox(tr("Text Formats"));
|
||||
|
||||
weekdayColorCombo = createColorComboBox();
|
||||
weekdayColorCombo->setCurrentIndex(
|
||||
weekdayColorCombo->findText(tr("Black")));
|
||||
|
||||
weekdayColorLabel = new QLabel(tr("&Weekday color:"));
|
||||
weekdayColorLabel->setBuddy(weekdayColorCombo);
|
||||
|
||||
weekendColorCombo = createColorComboBox();
|
||||
weekendColorCombo->setCurrentIndex(
|
||||
weekendColorCombo->findText(tr("Red")));
|
||||
|
||||
weekendColorLabel = new QLabel(tr("Week&end color:"));
|
||||
weekendColorLabel->setBuddy(weekendColorCombo);
|
||||
|
||||
headerTextFormatCombo = new QComboBox;
|
||||
headerTextFormatCombo->addItem(tr("Bold"));
|
||||
headerTextFormatCombo->addItem(tr("Italic"));
|
||||
headerTextFormatCombo->addItem(tr("Plain"));
|
||||
|
||||
headerTextFormatLabel = new QLabel(tr("&Header text:"));
|
||||
headerTextFormatLabel->setBuddy(headerTextFormatCombo);
|
||||
|
||||
firstFridayCheckBox = new QCheckBox(tr("&First Friday in blue"));
|
||||
|
||||
mayFirstCheckBox = new QCheckBox(tr("May &1 in red"));
|
||||
|
||||
connect(weekdayColorCombo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(weekdayFormatChanged()));
|
||||
connect(weekendColorCombo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(weekendFormatChanged()));
|
||||
connect(headerTextFormatCombo, SIGNAL(currentIndexChanged(QString)),
|
||||
this, SLOT(reformatHeaders()));
|
||||
connect(firstFridayCheckBox, SIGNAL(toggled(bool)),
|
||||
this, SLOT(reformatCalendarPage()));
|
||||
connect(mayFirstCheckBox, SIGNAL(toggled(bool)),
|
||||
this, SLOT(reformatCalendarPage()));
|
||||
|
||||
QHBoxLayout *checkBoxLayout = new QHBoxLayout;
|
||||
checkBoxLayout->addWidget(firstFridayCheckBox);
|
||||
checkBoxLayout->addStretch();
|
||||
checkBoxLayout->addWidget(mayFirstCheckBox);
|
||||
|
||||
QGridLayout *outerLayout = new QGridLayout;
|
||||
outerLayout->addWidget(weekdayColorLabel, 0, 0);
|
||||
outerLayout->addWidget(weekdayColorCombo, 0, 1);
|
||||
outerLayout->addWidget(weekendColorLabel, 1, 0);
|
||||
outerLayout->addWidget(weekendColorCombo, 1, 1);
|
||||
outerLayout->addWidget(headerTextFormatLabel, 2, 0);
|
||||
outerLayout->addWidget(headerTextFormatCombo, 2, 1);
|
||||
outerLayout->addLayout(checkBoxLayout, 3, 0, 1, 2);
|
||||
textFormatsGroupBox->setLayout(outerLayout);
|
||||
|
||||
weekdayFormatChanged();
|
||||
weekendFormatChanged();
|
||||
reformatHeaders();
|
||||
reformatCalendarPage();
|
||||
}
|
||||
|
||||
QComboBox *Window::createColorComboBox()
|
||||
{
|
||||
QComboBox *comboBox = new QComboBox;
|
||||
comboBox->addItem(tr("Red"), Qt::red);
|
||||
comboBox->addItem(tr("Blue"), Qt::blue);
|
||||
comboBox->addItem(tr("Black"), Qt::black);
|
||||
comboBox->addItem(tr("Magenta"), Qt::magenta);
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
//#include "moc_calwidget.cpp"
|
121
Tests/QtAutomoc/calwidget.h
Normal file
121
Tests/QtAutomoc/calwidget.h
Normal file
@ -0,0 +1,121 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef WINDOW_H
|
||||
#define WINDOW_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QCalendarWidget;
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QDate;
|
||||
class QDateEdit;
|
||||
class QGridLayout;
|
||||
class QGroupBox;
|
||||
class QLabel;
|
||||
|
||||
class Window : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Window();
|
||||
|
||||
private slots:
|
||||
void localeChanged(int index);
|
||||
void firstDayChanged(int index);
|
||||
void selectionModeChanged(int index);
|
||||
void horizontalHeaderChanged(int index);
|
||||
void verticalHeaderChanged(int index);
|
||||
void selectedDateChanged();
|
||||
void minimumDateChanged(const QDate &date);
|
||||
void maximumDateChanged(const QDate &date);
|
||||
void weekdayFormatChanged();
|
||||
void weekendFormatChanged();
|
||||
void reformatHeaders();
|
||||
void reformatCalendarPage();
|
||||
|
||||
private:
|
||||
void createPreviewGroupBox();
|
||||
void createGeneralOptionsGroupBox();
|
||||
void createDatesGroupBox();
|
||||
void createTextFormatsGroupBox();
|
||||
QComboBox *createColorComboBox();
|
||||
|
||||
QGroupBox *previewGroupBox;
|
||||
QGridLayout *previewLayout;
|
||||
QCalendarWidget *calendar;
|
||||
|
||||
QGroupBox *generalOptionsGroupBox;
|
||||
QLabel *localeLabel;
|
||||
QLabel *firstDayLabel;
|
||||
QLabel *selectionModeLabel;
|
||||
QLabel *horizontalHeaderLabel;
|
||||
QLabel *verticalHeaderLabel;
|
||||
QComboBox *localeCombo;
|
||||
QComboBox *firstDayCombo;
|
||||
QComboBox *selectionModeCombo;
|
||||
QCheckBox *gridCheckBox;
|
||||
QCheckBox *navigationCheckBox;
|
||||
QComboBox *horizontalHeaderCombo;
|
||||
QComboBox *verticalHeaderCombo;
|
||||
|
||||
QGroupBox *datesGroupBox;
|
||||
QLabel *currentDateLabel;
|
||||
QLabel *minimumDateLabel;
|
||||
QLabel *maximumDateLabel;
|
||||
QDateEdit *currentDateEdit;
|
||||
QDateEdit *minimumDateEdit;
|
||||
QDateEdit *maximumDateEdit;
|
||||
|
||||
QGroupBox *textFormatsGroupBox;
|
||||
QLabel *weekdayColorLabel;
|
||||
QLabel *weekendColorLabel;
|
||||
QLabel *headerTextFormatLabel;
|
||||
QComboBox *weekdayColorCombo;
|
||||
QComboBox *weekendColorCombo;
|
||||
QComboBox *headerTextFormatCombo;
|
||||
|
||||
QCheckBox *firstFridayCheckBox;
|
||||
QCheckBox *mayFirstCheckBox;
|
||||
};
|
||||
|
||||
#endif
|
153
Tests/QtAutomoc/codeeditor.cpp
Normal file
153
Tests/QtAutomoc/codeeditor.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
#include "codeeditor.h"
|
||||
|
||||
|
||||
CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent)
|
||||
{
|
||||
lineNumberArea = new LineNumberArea(this);
|
||||
|
||||
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
|
||||
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
|
||||
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
|
||||
|
||||
updateLineNumberAreaWidth(0);
|
||||
highlightCurrentLine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CodeEditor::lineNumberAreaWidth()
|
||||
{
|
||||
int digits = 1;
|
||||
int max = qMax(1, blockCount());
|
||||
while (max >= 10) {
|
||||
max /= 10;
|
||||
++digits;
|
||||
}
|
||||
|
||||
int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
|
||||
{
|
||||
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
|
||||
{
|
||||
if (dy)
|
||||
lineNumberArea->scroll(0, dy);
|
||||
else
|
||||
lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
|
||||
|
||||
if (rect.contains(viewport()->rect()))
|
||||
updateLineNumberAreaWidth(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CodeEditor::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
QPlainTextEdit::resizeEvent(e);
|
||||
|
||||
QRect cr = contentsRect();
|
||||
lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CodeEditor::highlightCurrentLine()
|
||||
{
|
||||
QList<QTextEdit::ExtraSelection> extraSelections;
|
||||
|
||||
if (!isReadOnly()) {
|
||||
QTextEdit::ExtraSelection selection;
|
||||
|
||||
QColor lineColor = QColor(Qt::yellow).lighter(160);
|
||||
|
||||
selection.format.setBackground(lineColor);
|
||||
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
|
||||
selection.cursor = textCursor();
|
||||
selection.cursor.clearSelection();
|
||||
extraSelections.append(selection);
|
||||
}
|
||||
|
||||
setExtraSelections(extraSelections);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter painter(lineNumberArea);
|
||||
painter.fillRect(event->rect(), Qt::lightGray);
|
||||
|
||||
|
||||
QTextBlock block = firstVisibleBlock();
|
||||
int blockNumber = block.blockNumber();
|
||||
int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
|
||||
int bottom = top + (int) blockBoundingRect(block).height();
|
||||
|
||||
while (block.isValid() && top <= event->rect().bottom()) {
|
||||
if (block.isVisible() && bottom >= event->rect().top()) {
|
||||
QString number = QString::number(blockNumber + 1);
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
|
||||
Qt::AlignRight, number);
|
||||
}
|
||||
|
||||
block = block.next();
|
||||
top = bottom;
|
||||
bottom = top + (int) blockBoundingRect(block).height();
|
||||
++blockNumber;
|
||||
}
|
||||
}
|
||||
|
||||
#include "codeeditor.moc"
|
99
Tests/QtAutomoc/codeeditor.h
Normal file
99
Tests/QtAutomoc/codeeditor.h
Normal file
@ -0,0 +1,99 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CODEEDITOR_H
|
||||
#define CODEEDITOR_H
|
||||
|
||||
#include <QPlainTextEdit>
|
||||
#include <QObject>
|
||||
|
||||
class QPaintEvent;
|
||||
class QResizeEvent;
|
||||
class QSize;
|
||||
class QWidget;
|
||||
|
||||
class LineNumberArea;
|
||||
|
||||
|
||||
class CodeEditor : public QPlainTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CodeEditor(QWidget *parent = 0);
|
||||
|
||||
void lineNumberAreaPaintEvent(QPaintEvent *event);
|
||||
int lineNumberAreaWidth();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private slots:
|
||||
void updateLineNumberAreaWidth(int newBlockCount);
|
||||
void highlightCurrentLine();
|
||||
void updateLineNumberArea(const QRect &, int);
|
||||
|
||||
private:
|
||||
QWidget *lineNumberArea;
|
||||
};
|
||||
|
||||
|
||||
class LineNumberArea : public QWidget
|
||||
{
|
||||
public:
|
||||
LineNumberArea(CodeEditor *editor) : QWidget(editor) {
|
||||
codeEditor = editor;
|
||||
}
|
||||
|
||||
QSize sizeHint() const {
|
||||
return QSize(codeEditor->lineNumberAreaWidth(), 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) {
|
||||
codeEditor->lineNumberAreaPaintEvent(event);
|
||||
}
|
||||
|
||||
private:
|
||||
CodeEditor *codeEditor;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
58
Tests/QtAutomoc/main.cpp
Normal file
58
Tests/QtAutomoc/main.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
#include "codeeditor.h"
|
||||
#include "calwidget.h"
|
||||
|
||||
int main(int argv, char **args)
|
||||
{
|
||||
QApplication app(argv, args);
|
||||
|
||||
CodeEditor editor;
|
||||
editor.setWindowTitle(QObject::tr("Code Editor Example"));
|
||||
editor.show();
|
||||
|
||||
Window w;
|
||||
w.show();
|
||||
|
||||
return app.exec();
|
||||
}
|
Loading…
Reference in New Issue
Block a user