Merge remote-tracking branch 'origin/3.6'

Change-Id: Iddfa0d2f3c0fb8ba65c0e5d479ad8e2f2cb95685
This commit is contained in:
Eike Ziller
2015-10-26 10:55:45 +01:00
285 changed files with 6092 additions and 2844 deletions

1
.gitignore vendored
View File

@@ -196,6 +196,7 @@ tmp/
/tests/auto/treeviewfind/tst_treeviewfind /tests/auto/treeviewfind/tst_treeviewfind
/tests/auto/utils/ansiescapecodehandler/tst_ansiescapecodehandler /tests/auto/utils/ansiescapecodehandler/tst_ansiescapecodehandler
/tests/auto/utils/fileutils/tst_fileutils /tests/auto/utils/fileutils/tst_fileutils
/tests/auto/utils/templateengine/tst_templateengine
/tests/auto/utils_stringutils/tst_utils_stringutils /tests/auto/utils_stringutils/tst_utils_stringutils
/tests/auto/valgrind/callgrind/tst_callgrindparsertests /tests/auto/valgrind/callgrind/tst_callgrindparsertests
/tests/auto/valgrind/memcheck/modeldemo /tests/auto/valgrind/memcheck/modeldemo

127
dist/changes-3.6.0.md vendored Normal file
View File

@@ -0,0 +1,127 @@
Qt Creator version 3.6 contains bug fixes and new features.
The most important changes are listed in this document. For a complete
list of changes, see the Git log for the Qt Creator sources that
you can check out from the public Git repository. For example:
git clone git://code.qt.io/qt-creator/qt-creator.git
git log --cherry-pick --pretty=oneline origin/3.5..origin/3.6
General
* Added text zoom in application and compile output (QTCREATORBUG-12476)
* Fixed that context help was shown for current keyboard focus widget, even when
a tool tip with help icon was visible (QTCREATORBUG-5345)
Editing
* Added experimental editor for UML-like diagrams (`ModelEditor` plugin)
* Made it possible to use Qt Creator variables in snippets
* Fixed indentation in block selection mode (QTCREATORBUG-12697)
* Fixed that Qt Creator tried to write auto-save files in read-only
directories
* Fixed possible crash with code completion (QTCREATORBUG-14875)
Project Management
* Added actions for building without dependencies and for rebuilding
and cleaning with dependencies to context menu of project tree
(QTCREATORBUG-14606)
* Added option to synchronize kits between all projects in a session
(QTCREATORBUG-5823)
QMake Projects
* Changed project display names to be `QMAKE_PROJECT_NAME` if set
(QTCREATORBUG-13950)
* Fixed that `.pri` files were shown in flat list instead of tree
(QTCREATORBUG-487)
* Fixed that `QMAKE_EXT_H` was ignored for UI code model (QTCREATORBUG-14910)
* Fixed that `make` build step was not updated on environment changes
(QTCREATORBUG-14831)
CMake Projects
* Improved handling of projects with CMake errors (QTCREATORBUG-6903)
* Added option for `Debug`, `Release`, `ReleaseWithDebugInfo` and
`MinSizeRelease` build types (QTCREATORBUG-12219)
* Added auto-indent and parentheses and quote matching to CMake editor
C++ Support
* Added support for `noexcept`
* Clang code model
* Added diagnostic messages to editors
* Added Clang's Fix-its to refactoring actions (QTCREATORBUG-14868)
Debugging
* Made sub-registers editable
* Fixed breakpoint removal from disassembler view (QTCREATORBUG-14973)
* CDB
* Fixed auto-detection of CDB from Windows 10 Kits
* LLDB
* Fixed handling of large registers
* QML/JS Console
* Implemented lazy loading of sub-items
* Improved error reporting
Analyzer
* Improved diagnostics view to use tree view instead of list
QML Profiler
* Improved performance of timeline view (QTCREATORBUG-14983)
Qt Quick Designer
* Made Qt Quick Designer aware of QRC files in project
* Improved selection behavior with regard to z-order in form editor
(QTCREATORBUG-11703)
* Added `Go to Implementation` action from `.ui.qml` file to its
associated `.qml` file
* Added connection editor and path editor
Version Control Systems
* Subversion
* Fixed encoding issues for commit message (QTCREATORBUG-14965)
* Perforce
* Fixed showing differences of files in submit editor when using
P4CONFIG (QTCREATORBUG-14538)
TODO
* Added option to show TODOs only for current sub-project
Platform Specific
Windows
* Fixed detection of `cygwin` ABIs
OS X
* Added option for file system case-sensitivity and made it case-insensitive by
default (QTCREATORBUG-13507)
* Added option to set `DYLD_LIBRARY_PATH` and `DYLD_FRAMEWORK_PATH` in
run configurations (QTCREATORBUG-14022)
Android
* Fixed that QML syntax errors where not clickable in application output
(QTCREATORBUG-14832)
* Fixed deployment on devices without `readlink` (QTCREATORBUG-15006)
* Fixed debugging of signed applications (requires Qt 5.6) (QTCREATORBUG-13035)
iOS
* Improved error messages for deployment
Remote Linux
* Added support for ECDSA public keys with 384 and 521 bits,
ECDSA user keys, and ECDSA key creation
* Fixed environment and working directory for Valgrind analyzer

View File

@@ -47,6 +47,15 @@ Component.prototype.loaded = function()
} }
} }
Component.prototype.createOperationsForArchive = function(archive)
{
// if there are additional plugin 7zips, these must be extracted in .app/Contents on OS X
if (systemInfo.productType !== "osx" || archive.indexOf('qtcreator.7z') !== -1)
component.addOperation("Extract", archive, "@TargetDir@");
else
component.addOperation("Extract", archive, "@TargetDir@/Qt Creator.app/Contents");
}
Component.prototype.beginInstallation = function() Component.prototype.beginInstallation = function()
{ {
component.qtCreatorBinaryPath = installer.value("TargetDir"); component.qtCreatorBinaryPath = installer.value("TargetDir");

View File

@@ -0,0 +1,4 @@
[Paths]
Imports = ../../Imports/qtquick1
Qml2Imports = ../../Imports/qtquick2
Plugins = ../../PlugIns

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@@ -50,11 +50,15 @@
\section1 Setting Up Clang Static Analyzer \section1 Setting Up Clang Static Analyzer
You must have Clang installed to use the Clang Static Analyzer. On Windows, As a tested version of Clang is shipped together with Qt Creator, no manual
Clang version 3.6, or later, is required to use the MSVC tool chain. setup is required.
To set up the Clang Static Analyzer, select \uicontrol Tools > To profit from improved checkers in newer Clang versions, \QC can be set up
\uicontrol Options > \uicontrol Analyzer > to use those. However, only the shipped version of Clang is tested and known
to work. Other versions might not work at all.
To set up a particular Clang version for the Clang Static Analyzer, select
\uicontrol Tools > \uicontrol Options > \uicontrol Analyzer >
\uicontrol {Clang Static Analyzer} and check that the path to the Clang \uicontrol {Clang Static Analyzer} and check that the path to the Clang
executable is set correctly in the \uicontrol {Clang executable} field. executable is set correctly in the \uicontrol {Clang executable} field.

View File

@@ -26,7 +26,7 @@
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage creator-usability.html \previouspage creator-usability.html
\page creator-coding.html \page creator-coding.html
\nextpage creator-editor-functions.html \nextpage creator-modeling.html
\title Coding \title Coding
@@ -34,6 +34,12 @@
\list \list
\li \l{Modeling}
You can use the experimental model editor to create Universal
Modeling Language (UML) style models with structured diagrams and
store them in XML format.
\li \l{Writing Code} \li \l{Writing Code}
Writing, editing, and navigating in source code are core tasks in Writing, editing, and navigating in source code are core tasks in

View File

@@ -24,7 +24,7 @@
/*! /*!
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage creator-coding.html \previouspage creator-modeling.html
\page creator-editor-functions.html \page creator-editor-functions.html
\nextpage creator-coding-navigating.html \nextpage creator-coding-navigating.html

View File

@@ -895,7 +895,8 @@
snippet, select \uicontrol Add. Specify a trigger and, if the trigger is snippet, select \uicontrol Add. Specify a trigger and, if the trigger is
already in use, an optional variant, which appear in the list of suggestions already in use, an optional variant, which appear in the list of suggestions
when you write code. Also specify a text string or C++ or QML code construct when you write code. Also specify a text string or C++ or QML code construct
in the snippet editor, depending on the snippet category. in the snippet editor, depending on the snippet category. You can use
\l{Using Qt Creator Variables}{predefined variables} in snippets.
The snippet editor provides you with: The snippet editor provides you with:
@@ -913,7 +914,18 @@
Specify the variables for the snippets in the following format: Specify the variables for the snippets in the following format:
\c $variable$ \code
$variable$
\endcode
Specify \QC variables in the following format:
\code
%{variable}
\endcode
For example, the following variable expands to the name of the current
project: \c {%{CurrentProject:Name}}.
Use unique variable names within a snippet, because all instances of a Use unique variable names within a snippet, because all instances of a
variable are renamed when you specify a value for it. variable are renamed when you specify a value for it.

View File

@@ -0,0 +1,327 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator
**
**
** GNU Free Documentation License
**
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of this
** file.
**
**
****************************************************************************/
// **********************************************************************
// NOTE: the sections are not ordered by their logical order to avoid
// reshuffling the file each time the index order changes (i.e., often).
// Run the fixnavi.pl script to adjust the links to the index order.
// **********************************************************************
/*!
\contentspage {Qt Creator Manual}
\previouspage creator-coding.html
\page creator-modeling.html
\nextpage creator-editor-functions.html
\title Modeling
You can use the experimental model editor to create Universal Modeling
Language (UML) style models with structured diagrams. However, the editor
uses a variant of UML and only a subset of properties are provided for
specifying the appearance of model elements.
You can create the following types of diagrams:
\list
\li Package
\li Class
\li Component
\li Use case
\li Activity
\endlist
You can add elements to the diagrams and specify properties for them. You
can either use standard model elements or add your own elements with custom
icons.
\image qtcreator-modeleditor.png
You can add model elements to diagrams in the following ways:
\list
\li Drag and drop model elements from the element tool bar (1) to the
editor (2).
\li Select tool bar buttons (3) to add elements to the element tree (4).
\li Drag elements from the element tree to the editor to add them and
all their relations to the diagram.
\li Drag and drop source files from \uicontrol Projects to the editor
to add C++ classes or components to a class or component diagram.
\endlist
You can group elements by surrounding them with a boundary. When you move
the boundary, all elements within it are moved together. Similarly, classes
that you lay on packages are moved with the packages. You can move
individual elements and modify their properties (5) by selecting them. You
can also use \e multiselection to group elements temporarily.
Drag the mouse over elements to select them and apply actions such as
changing their \e stereotype or color. A stereotype is a classifier for
elements, such as \e entity, \e control, \e interface, or \e boundary. An
entity is usually a class that is used to store data. For some stereotypes,
a custom icon is defined. You can assign several comma-separated stereotypes
to one element.
To print diagrams, press \key Ctrl+C when no elements are selected in
the editor to copy all elements to the clipboard by using 300 dpi. Then
paste the diagram to an application that can print images.
\section1 Creating Models
To create models:
\list 1
\li Select \uicontrol Help > \uicontrol {About Plugins} >
\uicontrol Modeling > \uicontrol ModelEditor and restart \QC to
enable the plugin.
\li Select \uicontrol File > \uicontrol {New File or Project} >
\uicontrol Modeling > \uicontrol Model > \uicontrol Choose to
create a model.
\li Drag and drop model elements to the editor and select them to
specify properties for them:
\list 1
\li In the \uicontrol Stereotypes field, enter the stereotype to
apply to the model element or select a predefined stereotype
from the list.
\li In the \uicontrol Name field, give a name to the model element.
\li Select the \uicontrol {Auto sized} check box to reset the
element to its default size after you have changed the element
size by dragging its borders.
\li In the \uicontrol Color field, select the color of the model
element.
\li In the \uicontrol Role field, select a \e role to make the model
element color lighter, darker, or softer or to remove color and
draw the element outline.
\li Select the \uicontrol Emphasized check box to draw the model
element with a thicker line.
\li In the \uicontrol {Stereotype display} field, select:
\list
\li \uicontrol Smart to display the stereotype as a
\uicontrol Label, a \uicontrol Decoration, or an
\uicontrol Icon, depending on the properties of the
element. For example, if a class has the stereotype
\uicontrol interface, it is displayed as an icon until
it becomes displayed members, after which it is
displayed as a decoration.
\li \uicontrol None to suppress the displaying of the
stereotype.
\li \uicontrol Label to display the stereotype as a line of
text using the standard form above the element name
even if the stereotype defines a custom icon.
\li \uicontrol Decoration to show the standard form of the
element with the stereotype as a small icon placed top
right if the stereotype defines a custom icon.
\li \uicontrol Icon to display the element using the custom
icon.
\endlist
\endlist
\li To create a relation between two elements, select the arrow icon
next to an element and drag it to the end point of the relation.
\li Select the relation to specify settings for it, according to its
type: inheritance, association, or dependency. You can specify the
following settings for dependency relations, which are available for
all element types:
\list 1
\li In the \uicontrol Stereotypes field, select the
\e stereotype to apply to the relation.
\li In the \uicontrol Name field, give a name to the relation.
\li In the \uicontrol Direction field, you can change the direction
of the connection or make it bidirectional.
\endlist
\li To create \e {sampling points} that divide a relation into two
connected lines, select a relation and press \key Shift+Click.
If possible, the end point of a relation is moved automatically to
draw the line to the next sampling point either vertically or
horizontally. To remove the selected sampling point, press
\key Ctrl+Click.
\li To group elements, drag and drop a \uicontrol Boundary element to
the editor and resize it to enclose the elements in the group.
\endlist
\section1 Creating Package Diagrams
You can add nested package elements to a package diagram. The depth of the
elements in the diagram corresponds to the depth of the structured model.
Elements stacked on other elements of the same type are automatically drawn
in a darker shade of the selected color.
\image qtcreator-modeleditor-packages.png
\section1 Creating Class Diagrams
\image qtcreator-modeleditor-classes.png
To create class diagrams:
\list 1
\li To add C++ classes to class diagrams, drag and drop files from
\uicontrol Projects to the editor, and select
\uicontrol {Add Class}.
\li In addition to the common element properties, you can specify the
following properties:
\list
\li In the \uicontrol Template field, specify the template to
use.
\li In the \uicontrol {Template display} field, select the
display format for the template:
\list
\li \uicontrol Smart displays the template as
\uicontrol Box or \uicontrol {Angle brackets},
depending on the class properties.
\li \uicontrol Box displays the template in a small box
with a dotted border in the top right corner of the
class icon.
\li \uicontrol {Angle brackets} writes the template
in angle brackets behind the class name using the
C++ syntax.
\endlist
\li In the \uicontrol Members field, specify members for the
class. Enter each member on a separate line using a C++
like syntax. For example, the following lines define the
method \c m that is private, virtual, and constant:
\code
private:
virtual int m(string a) const;
\endcode
\li Select \uicontrol {Clean Up} to format the contents of
the \uicontrol Members field depending on their visibility
(private, protected, public) and following the rules set for
whitespace, line breaks, and so on.
\li Select the \uicontrol {Show members} check box to show
the members in the diagram.
\endlist
\endlist
To navigate from a class in a diagram to the source code, double-click the
class in the editor or select \uicontrol {Show Definition} in the context
menu.
\section2 Adding Relations
Elements in class diagrams can have the following types of relations:
inheritance, association, and dependency. The end points of association
relations can have the following properties: role, cardinality, navigable,
and relationship.
To create self-relations, start creating a new association and press
\key Shift to create a new \e {intermediate point} while dragging the
association. Create another intermediate point and drop the association
at the same class.
To add more points, press \key Shift and click a relation. To delete a
point, press \key Ctrl and click a point.
\section1 Creating Component Diagrams
You can add source code components, such as libraries, databases, programs,
and architectural layers to a component diagram. To add components to
component diagrams, drag and drop source code from \uicontrol Projects to
the editor, and select \uicontrol {Add Component}.
To navigate from a component in a diagram to the source code, double-click
the component in the editor or select \uicontrol {Show Definition} in the
context menu.
\section1 Adding Custom Elements
The model editor provides the following built-in element types: package,
component, class, and item. For package, component, and class elements, you
can specify custom icons. The color, size, and form of the icon are
determined by a stereotype. If you attach the stereotype to an element, the
element icon is replaced by the custom icon. For example, you can attach the
entity and interface stereotypes to classes and the database stereotype to
components.
The use case and activity diagrams are examples of using the built-in
\e item element type to add custom elements. The item element has the form
of a simple rectangle. The use case illustrates how to use a custom icon for
an item. The attached stereotype is called \e usecase but it is hidden.
Therefore, if you drag the use case to the diagram, it is shown as a use
case but no stereotype appears to be defined and you can attach an
additional stereotype to the use case.
Color and icons are attached to elements in use case and activity diagrams
by using a simple definition file format. For example, the following code
adds the \c UseCase custom element:
\code
Icon UseCase
Title: "Use-Case"
Elements: item
Stereotype: 'usecase'
Display: icon
Width: 40
Height: 20
BaseColor: #5fb4f0
Begin
Ellipse 20, 10, 20, 10
End
\endcode
For more information about the available options, see \e standard.def
in the \e share/qtcreator/modeleditor directory in the \QC installation
directory.
You can add your own definition file and save it with the file extension
\e .def to add custom colors and icons for stereotypes, elements, or tool
bars.
*/

View File

@@ -321,6 +321,12 @@
change the default suffix of a file, select \uicontrol Tools > \uicontrol Options > change the default suffix of a file, select \uicontrol Tools > \uicontrol Options >
\uicontrol {C++} > \uicontrol {File Naming}. \uicontrol {C++} > \uicontrol {File Naming}.
\image qtcreator-options-cpp-files.png "File Naming tab in Options"
In the \uicontrol {License template} field, you can use
\l{Using Variables in Wizards}{predefined wizard variables} to specify the
path and filename of the license to use in the source and header files.
You can create your own project and class wizards. For more information, You can create your own project and class wizards. For more information,
see \l{Adding New Custom Wizards}. see \l{Adding New Custom Wizards}.

View File

@@ -76,6 +76,7 @@
\row \row
\li \b {\l{Coding}} \li \b {\l{Coding}}
\list \list
\li \l{Modeling}
\li \l{Writing Code} \li \l{Writing Code}
\li \l{Finding} \li \l{Finding}
\li \l{Refactoring} \li \l{Refactoring}
@@ -195,6 +196,7 @@
\endlist \endlist
\li \l{Coding} \li \l{Coding}
\list \list
\li \l{Modeling}
\li \l{Writing Code} \li \l{Writing Code}
\list \list
\li \l{Working in Edit Mode} \li \l{Working in Edit Mode}

164
scripts/common.py Normal file
View File

@@ -0,0 +1,164 @@
#############################################################################
##
## Copyright (C) 2015 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing
##
## This file is part of Qt Creator.
##
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms and
## conditions see http://www.qt.io/terms-conditions. For further information
## use the contact form at http://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 2.1 or version 3 as published by the Free
## Software Foundation and appearing in the file LICENSE.LGPLv21 and
## LICENSE.LGPLv3 included in the packaging of this file. Please review the
## following information to ensure the GNU Lesser General Public License
## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
##
## In addition, as a special exception, The Qt Company gives you certain additional
## rights. These rights are described in The Qt Company LGPL Exception
## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
##
#############################################################################
import os
import shutil
import subprocess
import sys
def is_windows_platform():
return sys.platform.startswith('win')
def is_linux_platform():
return sys.platform.startswith('linux')
def is_mac_platform():
return sys.platform.startswith('darwin')
# copy of shutil.copytree that does not bail out if the target directory already exists
# and that does not create empty directories
def copytree(src, dst, symlinks=False, ignore=None):
def ensure_dir(destdir, ensure):
if ensure and not os.path.isdir(destdir):
os.makedirs(destdir)
return False
names = os.listdir(src)
if ignore is not None:
ignored_names = ignore(src, names)
else:
ignored_names = set()
needs_ensure_dest_dir = True
errors = []
for name in names:
if name in ignored_names:
continue
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
if symlinks and os.path.islink(srcname):
needs_ensure_dest_dir = ensure_dir(dst, needs_ensure_dest_dir)
linkto = os.readlink(srcname)
os.symlink(linkto, dstname)
elif os.path.isdir(srcname):
copytree(srcname, dstname, symlinks, ignore)
else:
needs_ensure_dest_dir = ensure_dir(dst, needs_ensure_dest_dir)
shutil.copy2(srcname, dstname)
# XXX What about devices, sockets etc.?
except (IOError, os.error) as why:
errors.append((srcname, dstname, str(why)))
# catch the Error from the recursive copytree so that we can
# continue with other files
except shutil.Error as err:
errors.extend(err.args[0])
try:
if os.path.exists(dst):
shutil.copystat(src, dst)
except shutil.WindowsError:
# can't copy file access times on Windows
pass
except OSError as why:
errors.extend((src, dst, str(why)))
if errors:
raise shutil.Error(errors)
def get_qt_install_info(qmake_bin):
output = subprocess.check_output([qmake_bin, '-query'])
lines = output.strip().split('\n')
info = {}
for line in lines:
(var, sep, value) = line.partition(':')
info[var.strip()] = value.strip()
return info
def get_rpath(libfilepath, chrpath=None):
if chrpath is None:
chrpath = 'chrpath'
try:
output = subprocess.check_output([chrpath, '-l', libfilepath]).strip()
except subprocess.CalledProcessError: # no RPATH or RUNPATH
return []
marker = 'RPATH='
index = output.find(marker)
if index < 0:
marker = 'RUNPATH='
index = output.find(marker)
if index < 0:
return []
return output[index + len(marker):].split(':')
def fix_rpaths(path, qt_deploy_path, qt_install_info, chrpath=None):
if chrpath is None:
chrpath = 'chrpath'
qt_install_prefix = qt_install_info['QT_INSTALL_PREFIX']
qt_install_libs = qt_install_info['QT_INSTALL_LIBS']
def fix_rpaths_helper(filepath):
rpath = get_rpath(filepath, chrpath)
if len(rpath) <= 0:
return
# remove previous Qt RPATH
new_rpath = filter(lambda path: not path.startswith(qt_install_prefix) and not path.startswith(qt_install_libs),
rpath)
# add Qt RPATH if necessary
relative_path = os.path.relpath(qt_deploy_path, os.path.dirname(filepath))
if relative_path == '.':
relative_path = ''
else:
relative_path = '/' + relative_path
qt_rpath = '$ORIGIN' + relative_path
if not any((path == qt_rpath) for path in rpath):
new_rpath.append(qt_rpath)
# change RPATH
if len(new_rpath) > 0:
subprocess.check_call([chrpath, '-r', ':'.join(new_rpath), filepath])
else: # no RPATH / RUNPATH left. delete.
subprocess.check_call([chrpath, '-d', filepath])
def is_unix_executable(filepath):
# Whether a file is really a binary executable and not a script and not a symlink (unix only)
if os.path.exists(filepath) and os.access(filepath, os.X_OK) and not os.path.islink(filepath):
with open(filepath) as f:
return f.read(2) != "#!"
def is_unix_library(filepath):
# Whether a file is really a library and not a symlink (unix only)
return os.path.basename(filepath).find('.so') != -1 and not os.path.islink(filepath)
for dirpath, dirnames, filenames in os.walk(path):
for filename in filenames:
filepath = os.path.join(dirpath, filename)
if is_unix_executable(filepath) or is_unix_library(filepath):
fix_rpaths_helper(filepath)

View File

@@ -36,6 +36,8 @@ import string
import shutil import shutil
from glob import glob from glob import glob
import common
ignoreErrors = False ignoreErrors = False
debug_build = False debug_build = False
@@ -50,7 +52,7 @@ def which(program):
if fpath: if fpath:
if is_exe(program): if is_exe(program):
return program return program
if sys.platform.startswith('win'): if common.is_windows_platform():
if is_exe(program + ".exe"): if is_exe(program + ".exe"):
return program + ".exe" return program + ".exe"
else: else:
@@ -58,7 +60,7 @@ def which(program):
exe_file = os.path.join(path, program) exe_file = os.path.join(path, program)
if is_exe(exe_file): if is_exe(exe_file):
return exe_file return exe_file
if sys.platform.startswith('win'): if common.is_windows_platform():
if is_exe(exe_file + ".exe"): if is_exe(exe_file + ".exe"):
return exe_file + ".exe" return exe_file + ".exe"
@@ -86,44 +88,6 @@ def op_failed(details = None):
else: else:
print("Error: operation failed, but proceeding gracefully.") print("Error: operation failed, but proceeding gracefully.")
def fix_rpaths_helper(chrpath_bin, install_dir, dirpath, filenames):
# patch file
for filename in filenames:
fpath = os.path.join(dirpath, filename)
relpath = os.path.relpath(install_dir+'/lib/qtcreator', dirpath)
relpluginpath = os.path.relpath(install_dir+'/lib/qtcreator/plugins', dirpath)
command = [chrpath_bin, '-r', '$ORIGIN/'+relpath+':$ORIGIN/'+relpluginpath, fpath]
print fpath, ':', command
try:
subprocess.check_call(command)
except:
op_failed()
def check_unix_binary_exec_helper(dirpath, filename):
""" Whether a file is really a binary executable and not a script (unix only)"""
fpath = os.path.join(dirpath, filename)
if os.path.exists(fpath) and os.access(fpath, os.X_OK):
with open(fpath) as f:
return f.read(2) != "#!"
def check_unix_library_helper(dirpath, filename):
""" Whether a file is really a library and not a symlink (unix only)"""
fpath = os.path.join(dirpath, filename)
return filename.find('.so') != -1 and not os.path.islink(fpath)
def fix_rpaths(chrpath_bin, install_dir):
print "fixing rpaths..."
for dirpath, dirnames, filenames in os.walk(os.path.join(install_dir, 'bin')):
#TODO remove library_helper once all libs moved out of bin/ on linux
filenames = [filename for filename in filenames if check_unix_binary_exec_helper(dirpath, filename) or check_unix_library_helper(dirpath, filename)]
fix_rpaths_helper(chrpath_bin, install_dir, dirpath, filenames)
for dirpath, dirnames, filenames in os.walk(os.path.join(install_dir, 'libexec', 'qtcreator')):
filenames = [filename for filename in filenames if check_unix_binary_exec_helper(dirpath, filename)]
fix_rpaths_helper(chrpath_bin, install_dir, dirpath, filenames)
for dirpath, dirnames, filenames in os.walk(os.path.join(install_dir, 'lib')):
filenames = [filename for filename in filenames if check_unix_library_helper(dirpath, filename)]
fix_rpaths_helper(chrpath_bin, install_dir, dirpath, filenames)
def windows_debug_files_filter(filename): def windows_debug_files_filter(filename):
ignore_patterns = ['.lib', '.pdb', '.exp', '.ilk'] ignore_patterns = ['.lib', '.pdb', '.exp', '.ilk']
for ip in ignore_patterns: for ip in ignore_patterns:
@@ -132,7 +96,7 @@ def windows_debug_files_filter(filename):
return False return False
def copy_ignore_patterns_helper(dir, filenames): def copy_ignore_patterns_helper(dir, filenames):
if not sys.platform.startswith('win'): if not common.is_windows_platform:
return filenames return filenames
if debug_build: if debug_build:
@@ -146,17 +110,17 @@ def copy_ignore_patterns_helper(dir, filenames):
def copy_qt_libs(install_dir, qt_libs_dir, qt_plugin_dir, qt_import_dir, qt_qml_dir, plugins, imports): def copy_qt_libs(install_dir, qt_libs_dir, qt_plugin_dir, qt_import_dir, qt_qml_dir, plugins, imports):
print "copying Qt libraries..." print "copying Qt libraries..."
if sys.platform.startswith('win'): if common.is_windows_platform():
libraries = glob(os.path.join(qt_libs_dir, '*.dll')) libraries = glob(os.path.join(qt_libs_dir, '*.dll'))
else: else:
libraries = glob(os.path.join(qt_libs_dir, '*.so.*')) libraries = glob(os.path.join(qt_libs_dir, '*.so.*'))
if sys.platform.startswith('win'): if common.is_windows_platform():
dest = os.path.join(install_dir, 'bin') dest = os.path.join(install_dir, 'bin')
else: else:
dest = os.path.join(install_dir, 'lib', 'qtcreator') dest = os.path.join(install_dir, 'lib', 'qtcreator')
if sys.platform.startswith('win'): if common.is_windows_platform():
if debug_build: if debug_build:
libraries = filter(lambda library: is_debug(library), libraries) libraries = filter(lambda library: is_debug(library), libraries)
else: else:
@@ -174,7 +138,7 @@ def copy_qt_libs(install_dir, qt_libs_dir, qt_plugin_dir, qt_import_dir, qt_qml_
shutil.copy(library, dest) shutil.copy(library, dest)
copy_ignore_func = None copy_ignore_func = None
if sys.platform.startswith('win'): if common.is_windows_platform():
copy_ignore_func = copy_ignore_patterns_helper copy_ignore_func = copy_ignore_patterns_helper
print "Copying plugins:", plugins print "Copying plugins:", plugins
@@ -184,7 +148,7 @@ def copy_qt_libs(install_dir, qt_libs_dir, qt_plugin_dir, qt_import_dir, qt_qml_
shutil.rmtree(target) shutil.rmtree(target)
pluginPath = os.path.join(qt_plugin_dir, plugin) pluginPath = os.path.join(qt_plugin_dir, plugin)
if (os.path.exists(pluginPath)): if (os.path.exists(pluginPath)):
shutil.copytree(pluginPath, target, ignore=copy_ignore_func, symlinks=True) common.copytree(pluginPath, target, ignore=copy_ignore_func, symlinks=True)
print "Copying imports:", imports print "Copying imports:", imports
for qtimport in imports: for qtimport in imports:
@@ -193,23 +157,24 @@ def copy_qt_libs(install_dir, qt_libs_dir, qt_plugin_dir, qt_import_dir, qt_qml_
shutil.rmtree(target) shutil.rmtree(target)
import_path = os.path.join(qt_import_dir, qtimport) import_path = os.path.join(qt_import_dir, qtimport)
if os.path.exists(import_path): if os.path.exists(import_path):
shutil.copytree(import_path, target, ignore=copy_ignore_func, symlinks=True) common.copytree(import_path, target, ignore=copy_ignore_func, symlinks=True)
if (os.path.exists(qt_qml_dir)): if (os.path.exists(qt_qml_dir)):
print "Copying qt quick 2 imports" print "Copying qt quick 2 imports"
target = os.path.join(install_dir, 'bin', 'qml') target = os.path.join(install_dir, 'bin', 'qml')
if (os.path.exists(target)): if (os.path.exists(target)):
shutil.rmtree(target) shutil.rmtree(target)
shutil.copytree(qt_qml_dir, target, ignore=copy_ignore_func, symlinks=True) common.copytree(qt_qml_dir, target, ignore=copy_ignore_func, symlinks=True)
def add_qt_conf(install_dir): def add_qt_conf(target_dir, install_dir):
print "Creating qt.conf:" qtconf_filepath = os.path.join(target_dir, 'qt.conf')
f = open(install_dir + '/bin/qt.conf', 'w') print('Creating qt.conf in "{0}":'.format(qtconf_filepath))
f = open(qtconf_filepath, 'w')
f.write('[Paths]\n') f.write('[Paths]\n')
f.write('Libraries=../lib/qtcreator\n') f.write('Libraries={0}\n'.format(os.path.relpath(os.path.join(install_dir, 'lib', 'qtcreator'), target_dir).replace('\\', '/')))
f.write('Plugins=plugins\n') f.write('Plugins={0}\n'.format(os.path.relpath(os.path.join(install_dir, 'bin', 'plugins'), target_dir).replace('\\', '/')))
f.write('Imports=imports\n') f.write('Imports={0}\n'.format(os.path.relpath(os.path.join(install_dir, 'bin', 'imports'), target_dir).replace('\\', '/')))
f.write('Qml2Imports=qml\n') f.write('Qml2Imports={0}\n'.format(os.path.relpath(os.path.join(install_dir, 'bin', 'qml'), target_dir).replace('\\', '/')))
f.close() f.close()
def copy_translations(install_dir, qt_tr_dir): def copy_translations(install_dir, qt_tr_dir):
@@ -231,12 +196,14 @@ def copyPreservingLinks(source, destination):
else: else:
shutil.copy(source, destination) shutil.copy(source, destination)
def copy_libclang(install_dir, llvm_install_dir): def deploy_libclang(install_dir, llvm_install_dir, chrpath_bin):
# contains pairs of (source, target directory) # contains pairs of (source, target directory)
deployinfo = [] deployinfo = []
if sys.platform.startswith("win"): if common.is_windows_platform():
deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'libclang.dll'), deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'libclang.dll'),
os.path.join(install_dir, 'bin'))) os.path.join(install_dir, 'bin')))
deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'clang.exe'),
os.path.join(install_dir, 'bin')))
deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'clang-cl.exe'), deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'clang-cl.exe'),
os.path.join(install_dir, 'bin'))) os.path.join(install_dir, 'bin')))
else: else:
@@ -259,14 +226,20 @@ def copy_libclang(install_dir, llvm_install_dir):
for source, target in deployinfo: for source, target in deployinfo:
print source, '->', target print source, '->', target
copyPreservingLinks(source, target) copyPreservingLinks(source, target)
if common.is_linux_platform():
# libclang was statically compiled, so there is no need for the RPATHs
# and they are confusing when fixing RPATHs later in the process
print "removing libclang RPATHs..."
for source, target in deployinfo:
if not os.path.islink(target):
targetfilepath = target if not os.path.isdir(target) else os.path.join(target, os.path.basename(source))
subprocess.check_call([chrpath_bin, '-d', targetfilepath])
print resourcesource, '->', resourcetarget print resourcesource, '->', resourcetarget
if (os.path.exists(resourcetarget)): if (os.path.exists(resourcetarget)):
shutil.rmtree(resourcetarget) shutil.rmtree(resourcetarget)
shutil.copytree(resourcesource, resourcetarget, symlinks=True) common.copytree(resourcesource, resourcetarget, symlinks=True)
def readQmakeVar(qmake_bin, var):
pipe = os.popen(' '.join([qmake_bin, '-query', var]))
return pipe.read().rstrip('\n')
def main(): def main():
try: try:
@@ -298,40 +271,45 @@ def main():
print "Cannot find required binary 'qmake'." print "Cannot find required binary 'qmake'."
sys.exit(2) sys.exit(2)
if not sys.platform.startswith('win'): chrpath_bin = None
if common.is_linux_platform():
chrpath_bin = which('chrpath') chrpath_bin = which('chrpath')
if chrpath_bin == None: if chrpath_bin == None:
print "Cannot find required binary 'chrpath'." print "Cannot find required binary 'chrpath'."
sys.exit(2) sys.exit(2)
QT_INSTALL_LIBS = readQmakeVar(qmake_bin, 'QT_INSTALL_LIBS') qt_install_info = common.get_qt_install_info(qmake_bin)
QT_INSTALL_BINS = readQmakeVar(qmake_bin, 'QT_INSTALL_BINS') QT_INSTALL_LIBS = qt_install_info['QT_INSTALL_LIBS']
QT_INSTALL_PLUGINS = readQmakeVar(qmake_bin, 'QT_INSTALL_PLUGINS') QT_INSTALL_BINS = qt_install_info['QT_INSTALL_BINS']
QT_INSTALL_IMPORTS = readQmakeVar(qmake_bin, 'QT_INSTALL_IMPORTS') QT_INSTALL_PLUGINS = qt_install_info['QT_INSTALL_PLUGINS']
QT_INSTALL_QML = readQmakeVar(qmake_bin, 'QT_INSTALL_QML') QT_INSTALL_IMPORTS = qt_install_info['QT_INSTALL_IMPORTS']
QT_INSTALL_TRANSLATIONS = readQmakeVar(qmake_bin, 'QT_INSTALL_TRANSLATIONS') QT_INSTALL_QML = qt_install_info['QT_INSTALL_QML']
QT_INSTALL_TRANSLATIONS = qt_install_info['QT_INSTALL_TRANSLATIONS']
plugins = ['accessible', 'codecs', 'designer', 'iconengines', 'imageformats', 'platformthemes', 'platforminputcontexts', 'platforms', 'printsupport', 'sqldrivers', 'xcbglintegrations'] plugins = ['accessible', 'codecs', 'designer', 'iconengines', 'imageformats', 'platformthemes', 'platforminputcontexts', 'platforms', 'printsupport', 'sqldrivers', 'xcbglintegrations']
imports = ['Qt', 'QtWebKit'] imports = ['Qt', 'QtWebKit']
if sys.platform.startswith('win'): if common.is_windows_platform():
global debug_build global debug_build
debug_build = is_debug_build(install_dir) debug_build = is_debug_build(install_dir)
if sys.platform.startswith('win'): if common.is_windows_platform():
copy_qt_libs(install_dir, QT_INSTALL_BINS, QT_INSTALL_PLUGINS, QT_INSTALL_IMPORTS, QT_INSTALL_QML, plugins, imports) copy_qt_libs(install_dir, QT_INSTALL_BINS, QT_INSTALL_PLUGINS, QT_INSTALL_IMPORTS, QT_INSTALL_QML, plugins, imports)
else: else:
copy_qt_libs(install_dir, QT_INSTALL_LIBS, QT_INSTALL_PLUGINS, QT_INSTALL_IMPORTS, QT_INSTALL_QML, plugins, imports) copy_qt_libs(install_dir, QT_INSTALL_LIBS, QT_INSTALL_PLUGINS, QT_INSTALL_IMPORTS, QT_INSTALL_QML, plugins, imports)
copy_translations(install_dir, QT_INSTALL_TRANSLATIONS) copy_translations(install_dir, QT_INSTALL_TRANSLATIONS)
if "LLVM_INSTALL_DIR" in os.environ: if "LLVM_INSTALL_DIR" in os.environ:
copy_libclang(install_dir, os.environ["LLVM_INSTALL_DIR"]) deploy_libclang(install_dir, os.environ["LLVM_INSTALL_DIR"], chrpath_bin)
if not sys.platform.startswith('win'): if not common.is_windows_platform():
fix_rpaths(chrpath_bin, install_dir) print "fixing rpaths..."
add_qt_conf(install_dir) common.fix_rpaths(install_dir, os.path.join(install_dir, 'lib', 'qtcreator'),
qt_install_info, chrpath_bin)
add_qt_conf(os.path.join(install_dir, 'libexec', 'qtcreator'), install_dir) # e.g. for qml2puppet
add_qt_conf(os.path.join(install_dir, 'bin'), install_dir)
if __name__ == "__main__": if __name__ == "__main__":
if sys.platform == 'darwin': if common.is_mac_platform():
print "Mac OS is not supported by this script, please use macqtdeploy!" print "Mac OS is not supported by this script, please use macqtdeploy!"
sys.exit(2) sys.exit(2)
else: else:

View File

@@ -46,6 +46,12 @@ if [ ! -f "$1/Contents/Resources/ios/qt.conf" ]; then
cp -f "$(dirname "${BASH_SOURCE[0]}")/../dist/installer/mac/ios_qt.conf" "$1/Contents/Resources/ios/qt.conf" || exit 1 cp -f "$(dirname "${BASH_SOURCE[0]}")/../dist/installer/mac/ios_qt.conf" "$1/Contents/Resources/ios/qt.conf" || exit 1
fi fi
# copy qml2puppet's qt.conf
if [ ! -f "$1/Contents/Resources/qmldesigner/qt.conf" ]; then
echo "- Copying qmldesigner/qt.conf"
cp -f "$(dirname "${BASH_SOURCE[0]}")/../dist/installer/mac/qmldesigner_qt.conf" "$1/Contents/Resources/qmldesigner/qt.conf" || exit 1
fi
# copy Qt translations # copy Qt translations
# check for known existing translation to avoid copying multiple times # check for known existing translation to avoid copying multiple times
if [ ! -f "$1/Contents/Resources/translations/qt_de.qm" ]; then if [ ! -f "$1/Contents/Resources/translations/qt_de.qm" ]; then
@@ -82,7 +88,7 @@ fi
if [ ! -d "$1/Contents/Frameworks/QtCore.framework" ]; then if [ ! -d "$1/Contents/Frameworks/QtCore.framework" ]; then
qml2puppetapp="$1/Contents/Resources/qml2puppet" qml2puppetapp="$1/Contents/Resources/qmldesigner/qml2puppet"
if [ -f "$qml2puppetapp" ]; then if [ -f "$qml2puppetapp" ]; then
qml2puppetArgument="-executable=$qml2puppetapp" qml2puppetArgument="-executable=$qml2puppetapp"
fi fi

View File

@@ -38,7 +38,7 @@ import shutil
import inspect import inspect
def usage(): def usage():
print('Usage: %s [-v|--version-string=versionstring] [-i|--installer-path=/path/to/installerfw] [-a|--archive=archive.7z] <outputname>' % os.path.basename(sys.argv[0])) print('Usage: %s [-v|--version-string=versionstring] [-i|--installer-path=/path/to/installerfw] [-a|--archive=archive.7z] [-d|--debug] <outputname>' % os.path.basename(sys.argv[0]))
def substitute_file(infile, outfile, substitutions): def substitute_file(infile, outfile, substitutions):
with open(infile, 'r') as f: with open(infile, 'r') as f:
@@ -53,7 +53,7 @@ def ifw_template_dir():
def main(): def main():
try: try:
opts, args = getopt.gnu_getopt(sys.argv[1:], 'hv:i:a:', ['help', 'version-string=', 'installer-path=', 'archive']) opts, args = getopt.gnu_getopt(sys.argv[1:], 'hv:i:a:d', ['help', 'version-string=', 'installer-path=', 'archive', 'debug'])
except: except:
usage() usage()
sys.exit(2) sys.exit(2)
@@ -64,7 +64,8 @@ def main():
version = '' version = ''
ifw_location = '' ifw_location = ''
archive = '' archives = []
debug = False
for o, a in opts: for o, a in opts:
if o in ('-h', '--help'): if o in ('-h', '--help'):
usage() usage()
@@ -74,7 +75,9 @@ def main():
if o in ('-i', '--installer-path'): if o in ('-i', '--installer-path'):
ifw_location = a ifw_location = a
if o in ('-a', '--archive'): if o in ('-a', '--archive'):
archive = a archives.append(a)
if o in ('-d', '--debug'):
debug = True
if (version == ''): if (version == ''):
raise Exception('Version not specified (--version-string)!') raise Exception('Version not specified (--version-string)!')
@@ -82,8 +85,8 @@ def main():
if (ifw_location == ''): if (ifw_location == ''):
raise Exception('Installer framework location not specified (--installer-path)!') raise Exception('Installer framework location not specified (--installer-path)!')
if (archive == ''): if not archives:
raise Exception('Archive not specified (--archive)!') raise ValueError('No archive(s) specified (--archive)!')
installer_name = args[0] installer_name = args[0]
config_postfix = '' config_postfix = ''
@@ -100,12 +103,15 @@ def main():
try: try:
temp_dir = tempfile.mkdtemp() temp_dir = tempfile.mkdtemp()
except: except:
raise Exception('Failed to create a temporary directory!') raise IOError('Failed to create a temporary directory!')
if debug:
print('Working directory: {0}'.format(temp_dir))
try: try:
substs = {} substs = {}
substs['version'] = version substs['version'] = version
substs['date'] = datetime.date.today().isoformat() substs['date'] = datetime.date.today().isoformat()
substs['archives'] = ','.join(archives)
template_dir = ifw_template_dir() template_dir = ifw_template_dir()
out_config_dir = os.path.join(temp_dir,'config') out_config_dir = os.path.join(temp_dir,'config')
@@ -127,11 +133,15 @@ def main():
data_path = os.path.join(out_packages_dir, 'org.qtproject.qtcreator.application', 'data') data_path = os.path.join(out_packages_dir, 'org.qtproject.qtcreator.application', 'data')
if not os.path.exists(data_path): if not os.path.exists(data_path):
os.makedirs(data_path) os.makedirs(data_path)
for archive in archives:
shutil.copy(archive, data_path) shutil.copy(archive, data_path)
ifw_call = [os.path.join(ifw_location, 'bin', 'binarycreator'), '-c', os.path.join(out_config_dir, config_name), '-p', out_packages_dir, installer_name, '--offline-only' ] ifw_call = [os.path.join(ifw_location, 'bin', 'binarycreator'), '-c', os.path.join(out_config_dir, config_name), '-p', out_packages_dir, installer_name, '--offline-only' ]
if debug:
ifw_call.append('-v')
subprocess.check_call(ifw_call, stderr=subprocess.STDOUT) subprocess.check_call(ifw_call, stderr=subprocess.STDOUT)
finally: finally:
if not debug:
print('Cleaning up...') print('Cleaning up...')
shutil.rmtree(temp_dir) shutil.rmtree(temp_dir)
print('Done.') print('Done.')

58
scripts/packagePlugins.py Executable file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/env python
#############################################################################
##
## Copyright (C) 2015 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing
##
## This file is part of Qt Creator.
##
## Commercial License Usage
## Licensees holding valid commercial Qt licenses may use this file in
## accordance with the commercial license agreement provided with the
## Software or, alternatively, in accordance with the terms contained in
## a written agreement between you and The Qt Company. For licensing terms and
## conditions see http://www.qt.io/terms-conditions. For further information
## use the contact form at http://www.qt.io/contact-us.
##
## GNU Lesser General Public License Usage
## Alternatively, this file may be used under the terms of the GNU Lesser
## General Public License version 2.1 or version 3 as published by the Free
## Software Foundation and appearing in the file LICENSE.LGPLv21 and
## LICENSE.LGPLv3 included in the packaging of this file. Please review the
## following information to ensure the GNU Lesser General Public License
## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
##
## In addition, as a special exception, The Qt Company gives you certain additional
## rights. These rights are described in The Qt Company LGPL Exception
## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
##
#############################################################################
import argparse
import os
import subprocess
import sys
import common
def parse_arguments():
parser = argparse.ArgumentParser(description="Deploy and 7z a directory of plugins.")
parser.add_argument('--7z', help='path to 7z binary',
default='7z.exe' if common.is_windows_platform() else '7z',
metavar='<7z_binary>', dest='sevenzip')
parser.add_argument('--qmake_binary', help='path to qmake binary which was used for compilation',
required=common.is_linux_platform(), metavar='<qmake_binary>')
parser.add_argument('source_directory', help='directory to deploy and 7z')
parser.add_argument('target_file', help='target file path of the resulting 7z')
return parser.parse_args()
if __name__ == "__main__":
arguments = parse_arguments()
if common.is_linux_platform():
qt_install_info = common.get_qt_install_info(arguments.qmake_binary)
common.fix_rpaths(arguments.source_directory,
os.path.join(arguments.source_directory, 'lib', 'qtcreator'),
qt_install_info)
subprocess.check_call([arguments.sevenzip, 'a', '-mx9', arguments.target_file,
os.path.join(arguments.source_directory, '*')])

View File

@@ -414,8 +414,6 @@ class DumperBase:
"personaltypes", "personaltypes",
] ]
self.interpreterSeq = 0
def resetCaches(self): def resetCaches(self):
# This is a cache mapping from 'type name' to 'display alternatives'. # This is a cache mapping from 'type name' to 'display alternatives'.
@@ -601,9 +599,6 @@ class DumperBase:
data = self.extractBlob(addr, size).toBytes() data = self.extractBlob(addr, size).toBytes()
return self.hexencode(data) return self.hexencode(data)
def readJsonFromMemory(self, addr, size):
return json.loads(self.hexdecode(self.readMemory(addr, size)))
def encodeByteArray(self, value, limit = 0): def encodeByteArray(self, value, limit = 0):
elided, data = self.encodeByteArrayHelper(self.extractPointer(value), limit) elided, data = self.encodeByteArrayHelper(self.extractPointer(value), limit)
return data return data
@@ -834,16 +829,99 @@ class DumperBase:
self.putSpecialValue(SpecialItemCountValue, count) self.putSpecialValue(SpecialItemCountValue, count)
self.putNumChild(count) self.putNumChild(count)
def dictToMi(self, value): def resultToMi(self, value):
if type(value) is bool: if type(value) is bool:
return '"%d"' % int(value) return '"%d"' % int(value)
if type(value) is dict: if type(value) is dict:
return '{' + ','.join(['%s=%s' % (k, self.dictToMi(v)) return '{' + ','.join(['%s=%s' % (k, self.resultToMi(v))
for (k, v) in list(value.items())]) + '}' for (k, v) in list(value.items())]) + '}'
if type(value) is list: if type(value) is list:
return '[' + ','.join([self.dictToMi(v) for v in value]) + ']' return '[' + ','.join([self.resultToMi(k)
for k in list(value.items())]) + ']'
return '"%s"' % value return '"%s"' % value
def variablesToMi(self, value, prefix):
if type(value) is bool:
return '"%d"' % int(value)
if type(value) is dict:
pairs = []
for (k, v) in list(value.items()):
if k == 'iname':
if v.startswith('.'):
v = '"%s%s"' % (prefix, v)
else:
v = '"%s"' % v
else:
v = self.variablesToMi(v, prefix)
pairs.append('%s=%s' % (k, v))
return '{' + ','.join(pairs) + '}'
if type(value) is list:
index = 0
pairs = []
for item in value:
if item.get('type', '') == 'function':
continue
name = item.get('name', '')
if len(name) == 0:
name = str(index)
index += 1
pairs.append((name, self.variablesToMi(item, prefix)))
pairs.sort(key = lambda pair: pair[0])
return '[' + ','.join([pair[1] for pair in pairs]) + ']'
return '"%s"' % value
def filterPrefix(self, prefix, items):
return [i[len(prefix):] for i in items if i.startswith(prefix)]
def tryFetchInterpreterVariables(self, args):
if not int(args.get('nativemixed', 0)):
return (False, '')
context = args.get('context', '')
if not len(context):
return (False, '')
expanded = args.get('expanded')
args['expanded'] = self.filterPrefix('local', expanded)
res = self.sendInterpreterRequest('variables', args)
if not res:
return (False, '')
reslist = []
for item in res.get('variables', {}):
if not 'iname' in item:
item['iname'] = '.' + item.get('name')
reslist.append(self.variablesToMi(item, 'local'))
watchers = args.get('watchers', None)
if watchers:
toevaluate = []
name2expr = {}
seq = 0
for watcher in watchers:
expr = self.hexdecode(watcher.get('exp'))
name = str(seq)
toevaluate.append({'name': name, 'expression': expr})
name2expr[name] = expr
seq += 1
args['expressions'] = toevaluate
args['expanded'] = self.filterPrefix('watch', expanded)
del args['watchers']
res = self.sendInterpreterRequest('expressions', args)
if res:
for item in res.get('expressions', {}):
name = item.get('name')
iname = 'watch.' + name
expr = name2expr.get(name)
item['iname'] = iname
item['wname'] = self.hexencode(expr)
item['exp'] = expr
reslist.append(self.variablesToMi(item, 'watch'))
return (True, 'data=[%s]' % ','.join(reslist))
def putField(self, name, value): def putField(self, name, value):
self.put('%s="%s",' % (name, value)) self.put('%s="%s",' % (name, value))
@@ -1753,34 +1831,86 @@ class DumperBase:
value = struct.unpack_from("!I", buf, offset)[0] value = struct.unpack_from("!I", buf, offset)[0]
return (value, offset + 4) return (value, offset + 4)
def readInterpreterOutput(self): def handleInterpreterMessage(self):
buf = self.parseAndEvaluate("qt_qmlDebugOutputBuffer")
size = self.parseAndEvaluate("qt_qmlDebugOutputLength")
return self.readJsonFromMemory(buf, size)
def handleInterpreterEvent(self):
""" Return True if inferior stopped """ """ Return True if inferior stopped """
buf = self.parseAndEvaluate("qt_qmlDebugEventBuffer") resdict = self.fetchInterpreterResult()
size = self.parseAndEvaluate("qt_qmlDebugEventLength")
resdict = self.readJsonFromMemory(buf, size)
warn("RES DICT : %s" % resdict)
return resdict.get('event') == 'break' return resdict.get('event') == 'break'
def reportInterpreterResult(self, resdict, args):
print('interpreterresult=%s,token="%s"'
% (self.resultToMi(resdict), args.get('token', -1)))
def reportInterpreterAsync(self, resdict, asyncclass):
print('interpreterasync=%s,asyncclass="%s"'
% (self.resultToMi(resdict), asyncclass))
def removeInterpreterBreakpoint(self, args): def removeInterpreterBreakpoint(self, args):
res = self.sendInterpreterRequest('removebreakpoint', { 'id' : args['id'] }) res = self.sendInterpreterRequest('removebreakpoint', { 'id' : args['id'] })
return res return res
def insertInterpreterBreakpoint(self, args): def insertInterpreterBreakpoint(self, args):
args['condition'] = self.hexdecode(args.get('condition', '')) args['condition'] = self.hexdecode(args.get('condition', ''))
warn("Insert interpreter breakpoint %s:%s (%s)" # Will fail if the service is not yet up and running.
% (args['file'], args['line'], args['condition'])) response = self.sendInterpreterRequest('setbreakpoint', args)
bp = self.doInsertInterpreterBreakpoint(args, False) resdict = args.copy()
return str(bp) bp = None if response is None else response.get("breakpoint", None)
if bp:
resdict['number'] = bp
resdict['pending'] = 0
else:
self.createResolvePendingBreakpointsHookBreakpoint(args)
resdict['number'] = -1
resdict['pending'] = 1
resdict['warning'] = 'Direct interpreter breakpoint insertion failed.'
self.reportInterpreterResult(resdict, args)
def resolvePendingInterpreterBreakpoint(self, args):
self.parseAndEvaluate('qt_qmlDebugEnableService("NativeQmlDebugger")')
response = self.sendInterpreterRequest('setbreakpoint', args)
bp = None if response is None else response.get("breakpoint", None)
resdict = args.copy()
if bp:
resdict['number'] = bp
resdict['pending'] = 0
else:
resdict['number'] = -1
resdict['pending'] = 0
resdict['error'] = 'Pending interpreter breakpoint insertion failed.'
self.reportInterpreterAsync(resdict, 'breakpointmodified')
def fetchInterpreterResult(self):
buf = self.parseAndEvaluate("qt_qmlDebugMessageBuffer")
size = self.parseAndEvaluate("qt_qmlDebugMessageLength")
msg = self.hexdecode(self.readMemory(buf, size))
# msg is a sequence of 'servicename<space>msglen<space>msg' items.
resdict = {} # Native payload.
while len(msg):
pos0 = msg.index(' ') # End of service name
pos1 = msg.index(' ', pos0 + 1) # End of message length
service = msg[0:pos0]
msglen = int(msg[pos0+1:pos1])
msgend = pos1+1+msglen
payload = msg[pos1+1:msgend]
msg = msg[msgend:]
if service == 'NativeQmlDebugger':
try:
resdict = json.loads(payload)
continue
except:
warn("Cannot parse native payload: %s" % payload)
else:
print('interpreteralien=%s'
% {'service': service, 'payload': self.hexencode(payload)})
try:
expr = 'qt_qmlDebugClearBuffer()'
res = self.parseAndEvaluate(expr)
except RuntimeError as error:
warn("Cleaning buffer failed: %s: %s" % (expr, error))
return resdict
def sendInterpreterRequest(self, command, args = {}): def sendInterpreterRequest(self, command, args = {}):
self.interpreterSeq += 1 encoded = json.dumps({ 'command': command, 'arguments': args })
cmd = { 'seq': self.interpreterSeq, 'type': 'request', 'command': command, 'arguments': args }
encoded = json.dumps(cmd)
hexdata = self.hexencode(encoded) hexdata = self.hexencode(encoded)
expr = 'qt_qmlDebugSendDataToService("NativeQmlDebugger","%s")' % hexdata expr = 'qt_qmlDebugSendDataToService("NativeQmlDebugger","%s")' % hexdata
try: try:
@@ -1792,21 +1922,10 @@ class DumperBase:
# Happens with LLDB and 'None' current thread. # Happens with LLDB and 'None' current thread.
warn("Interpreter command failed: %s: %s" % (encoded, error)) warn("Interpreter command failed: %s: %s" % (encoded, error))
return {} return {}
if not res: if not res:
warn("Interpreter command failed: %s " % encoded) warn("Interpreter command failed: %s " % encoded)
return {} return {}
resdict = self.readInterpreterOutput() return self.fetchInterpreterResult()
warn("Interpreter command output: '%s'" % resdict)
service = resdict.get("service")
if service == "NativeQmlDebugger":
messages = resdict.get("messages", [])
if len(messages) == 1:
return messages[0]
warn("Unexpected multiple interpreter messages: %s" % messages)
else:
warn("Interpreter result from alien service: %s" % service)
return {'messages': messages }
def executeStep(self, args): def executeStep(self, args):
if self.nativeMixed: if self.nativeMixed:
@@ -1829,23 +1948,22 @@ class DumperBase:
self.doContinue() self.doContinue()
def doInsertInterpreterBreakpoint(self, args, wasPending): def doInsertInterpreterBreakpoint(self, args, wasPending):
warn("DO INSERT INTERPRETER BREAKPOINT, WAS PENDING: %s" % wasPending) #warn("DO INSERT INTERPRETER BREAKPOINT, WAS PENDING: %s" % wasPending)
# Will fail if the service is not yet up and running. # Will fail if the service is not yet up and running.
response = self.sendInterpreterRequest('setbreakpoint', args) response = self.sendInterpreterRequest('setbreakpoint', args)
bp = None if response is None else response.get("breakpoint", None) bp = None if response is None else response.get("breakpoint", None)
if wasPending: if wasPending:
if not bp: if not bp:
warn("ERROR: Pending interpreter breakpoint insertion failed.") self.reportInterpreterResult({'bpnr': -1, 'pending': 1,
return -1 'error': 'Pending interpreter breakpoint insertion failed.'}, args)
return
else: else:
if not bp: if not bp:
warn("Direct interpreter breakpoint insertion failed.") self.reportInterpreterResult({'bpnr': -1, 'pending': 1,
warn("Make pending.") 'warning': 'Direct interpreter breakpoint insertion failed.'}, args)
self.createResolvePendingBreakpointsHookBreakpoint(args) self.createResolvePendingBreakpointsHookBreakpoint(args)
return -1 return
self.reportInterpreterResult({'bpnr': bp, 'pending': 0}, args)
warn("Resolved interpreter breakpoint: BP: %s" % bp)
return int(bp)
def isInternalInterpreterFrame(self, functionName): def isInternalInterpreterFrame(self, functionName):
if functionName is None: if functionName is None:
@@ -1875,6 +1993,11 @@ class DumperBase:
def extractInterpreterStack(self): def extractInterpreterStack(self):
return self.sendInterpreterRequest('backtrace', {'limit': 10 }) return self.sendInterpreterRequest('backtrace', {'limit': 10 })
def extractInterpreterVariables(self, args): def polishWatchers(self, watchers):
return self.sendInterpreterRequest('variables', args) out = []
for watcher in watchers:
iname = watcher.get('iname')
exp = self.hexdecode(watcher.get('exp'))
out.append({'iname': iname, 'expression': exp, 'name': exp })
return out

View File

@@ -220,12 +220,11 @@ class Dumper(DumperBase):
# These values will be kept between calls to 'fetchVariables'. # These values will be kept between calls to 'fetchVariables'.
self.isGdb = True self.isGdb = True
self.childEventAddress = None
self.typeCache = {} self.typeCache = {}
self.typesReported = {} self.typesReported = {}
self.typesToReport = {} self.typesToReport = {}
self.qtNamespaceToReport = None self.qtNamespaceToReport = None
self.interpreterBreakpoints = [] self.interpreterBreakpointResolvers = []
def prepare(self, args): def prepare(self, args):
self.output = [] self.output = []
@@ -359,12 +358,9 @@ class Dumper(DumperBase):
partialVariable = args.get("partialVariable", "") partialVariable = args.get("partialVariable", "")
isPartial = len(partialVariable) > 0 isPartial = len(partialVariable) > 0
if self.nativeMixed: (ok, res) = self.tryFetchInterpreterVariables(args)
context = args.get('context', '') if ok:
if len(context): safePrint(res)
res = self.extractInterpreterVariables(args)
if res:
safePrint('data=%s' % self.dictToMi(res.get('data', {})))
return return
# #
@@ -1607,7 +1603,7 @@ class Dumper(DumperBase):
objfile = fromNativePath(symtab.objfile.filename) objfile = fromNativePath(symtab.objfile.filename)
fileName = fromNativePath(symtab.fullname()) fileName = fromNativePath(symtab.fullname())
if self.nativeMixed and functionName == "qt_qmlDebugEventFromService": if self.nativeMixed and functionName == "qt_qmlDebugMessageAvailable":
interpreterStack = self.extractInterpreterStack() interpreterStack = self.extractInterpreterStack()
#print("EXTRACTED INTEPRETER STACK: %s" % interpreterStack) #print("EXTRACTED INTEPRETER STACK: %s" % interpreterStack)
for interpreterFrame in interpreterStack.get('frames', []): for interpreterFrame in interpreterStack.get('frames', []):
@@ -1645,17 +1641,15 @@ class Dumper(DumperBase):
self.dumper = dumper self.dumper = dumper
self.args = args self.args = args
spec = "qt_qmlDebugConnectorOpen" spec = "qt_qmlDebugConnectorOpen"
print("Preparing hook to resolve pending QML breakpoint at %s" % args)
super(Resolver, self).\ super(Resolver, self).\
__init__(spec, gdb.BP_BREAKPOINT, internal=True, temporary=False) __init__(spec, gdb.BP_BREAKPOINT, internal=True, temporary=False)
def stop(self): def stop(self):
bp = self.dumper.doInsertInterpreterBreakpoint(args, True) self.dumper.resolvePendingInterpreterBreakpoint(args)
print("Resolving QML breakpoint %s -> %s" % (args, bp))
self.enabled = False self.enabled = False
return False return False
self.interpreterBreakpoints.append(Resolver(self, args)) self.interpreterBreakpointResolvers.append(Resolver(self, args))
def exitGdb(self, _): def exitGdb(self, _):
gdb.execute("quit") gdb.execute("quit")
@@ -1804,26 +1798,14 @@ registerCommand("threadnames", threadnames)
# #
####################################################################### #######################################################################
class TriggeredBreakpointHookBreakpoint(gdb.Breakpoint): class InterpreterMessageBreakpoint(gdb.Breakpoint):
def __init__(self): def __init__(self):
spec = "qt_v4TriggeredBreakpointHook" spec = "qt_qmlDebugMessageAvailable"
super(TriggeredBreakpointHookBreakpoint, self).\ super(InterpreterMessageBreakpoint, self).\
__init__(spec, gdb.BP_BREAKPOINT, internal=True) __init__(spec, gdb.BP_BREAKPOINT, internal=True)
def stop(self): def stop(self):
print("QML engine stopped.") print("Interpreter event received.")
return True return theDumper.handleInterpreterMessage()
TriggeredBreakpointHookBreakpoint() InterpreterMessageBreakpoint()
class QmlEngineEventBreakpoint(gdb.Breakpoint):
def __init__(self):
spec = "qt_qmlDebugEventFromService"
super(QmlEngineEventBreakpoint, self).\
__init__(spec, gdb.BP_BREAKPOINT, internal=True)
def stop(self):
print("QML engine event received.")
return theDumper.handleInterpreterEvent()
QmlEngineEventBreakpoint()

View File

@@ -48,9 +48,6 @@ from dumper import *
qqWatchpointOffset = 10000 qqWatchpointOffset = 10000
def warn(message):
print('\n\nWARNING="%s",\n' % message.encode("latin1").replace('"', "'"))
def showException(msg, exType, exValue, exTraceback): def showException(msg, exType, exValue, exTraceback):
warn("**** CAUGHT EXCEPTION: %s ****" % msg) warn("**** CAUGHT EXCEPTION: %s ****" % msg)
import traceback import traceback
@@ -230,8 +227,7 @@ class Dumper(DumperBase):
self.voidPtrType_ = None self.voidPtrType_ = None
self.isShuttingDown_ = False self.isShuttingDown_ = False
self.isInterrupting_ = False self.isInterrupting_ = False
self.qmlBreakpointResolvers = {} self.interpreterBreakpointResolvers = []
self.qmlTriggeredBreakpoint = None
self.report('lldbversion=\"%s\"' % lldb.SBDebugger.GetVersionString()) self.report('lldbversion=\"%s\"' % lldb.SBDebugger.GetVersionString())
self.reportState("enginesetupok") self.reportState("enginesetupok")
@@ -549,7 +545,7 @@ class Dumper(DumperBase):
self.report('error="%s"' % result.GetError()) self.report('error="%s"' % result.GetError())
def put(self, stuff): def put(self, stuff):
self.out += stuff self.output += stuff
def isMovableType(self, type): def isMovableType(self, type):
if type.GetTypeClass() in (lldb.eTypeClassBuiltin, lldb.eTypeClassPointer): if type.GetTypeClass() in (lldb.eTypeClassBuiltin, lldb.eTypeClassPointer):
@@ -667,6 +663,7 @@ class Dumper(DumperBase):
self.sysRoot_ = args.get('sysRoot', '') self.sysRoot_ = args.get('sysRoot', '')
self.remoteChannel_ = args.get('remoteChannel', '') self.remoteChannel_ = args.get('remoteChannel', '')
self.platform_ = args.get('platform', '') self.platform_ = args.get('platform', '')
self.nativeMixed = int(args.get('nativemixed', 0))
self.ignoreStops = 0 self.ignoreStops = 0
self.silentStops = 0 self.silentStops = 0
@@ -689,12 +686,15 @@ class Dumper(DumperBase):
if self.sysRoot_: if self.sysRoot_:
self.debugger.SetCurrentPlatformSDKRoot(self.sysRoot_) self.debugger.SetCurrentPlatformSDKRoot(self.sysRoot_)
if os.path.isfile(self.executable_): if os.path.isfile(self.executable_):
self.target = self.debugger.CreateTarget(self.executable_, None, None, True, error) self.target = self.debugger.CreateTarget(self.executable_, None, None, True, error)
else: else:
self.target = self.debugger.CreateTarget(None, None, None, True, error) self.target = self.debugger.CreateTarget(None, None, None, True, error)
if self.nativeMixed:
self.interpreterEventBreakpoint = \
self.target.BreakpointCreateByName("qt_qmlDebugMessageAvailable")
state = 1 if self.target.IsValid() else 0 state = 1 if self.target.IsValid() else 0
self.reportResult('success="%s",msg="%s",exe="%s"' % (state, error, self.executable_), args) self.reportResult('success="%s",msg="%s",exe="%s"' % (state, error, self.executable_), args)
@@ -775,9 +775,11 @@ class Dumper(DumperBase):
def describeLocation(self, frame): def describeLocation(self, frame):
if int(frame.pc) == 0xffffffffffffffff: if int(frame.pc) == 0xffffffffffffffff:
return '' return ''
file = fileNameAsString(frame.line_entry.file) fileName = fileNameAsString(frame.line_entry.file)
function = frame.GetFunctionName()
line = frame.line_entry.line line = frame.line_entry.line
return 'location={file="%s",line="%s",addr="%s"}' % (file, line, frame.pc) return 'location={file="%s",line="%s",address="%s",function="%s"}' \
% (fileName, line, frame.pc, function)
def currentThread(self): def currentThread(self):
return None if self.process is None else self.process.GetSelectedThread() return None if self.process is None else self.process.GetSelectedThread()
@@ -847,8 +849,6 @@ class Dumper(DumperBase):
self.reportResult('msg="No thread"', args) self.reportResult('msg="No thread"', args)
return return
self.report(self.describeLocation(thread.GetFrameAtIndex(0))) # FIXME
isNativeMixed = int(args.get('nativemixed', 0)) isNativeMixed = int(args.get('nativemixed', 0))
limit = args.get('stacklimit', -1) limit = args.get('stacklimit', -1)
@@ -868,38 +868,27 @@ class Dumper(DumperBase):
pc = frame.GetPC() pc = frame.GetPC()
level = frame.idx level = frame.idx
addr = frame.GetPCAddress().GetLoadAddress(self.target) addr = frame.GetPCAddress().GetLoadAddress(self.target)
functionName = frame.GetFunctionName() functionName = frame.GetFunctionName()
if isNativeMixed and functionName == "::qt_qmlDebugMessageAvailable()":
interpreterStack = self.extractInterpreterStack()
for interpreterFrame in interpreterStack.get('frames', []):
function = interpreterFrame.get('function', '')
fileName = interpreterFrame.get('file', '')
language = interpreterFrame.get('language', '')
lineNumber = interpreterFrame.get('line', 0)
context = interpreterFrame.get('context', 0)
result += ('frame={function="%s",file="%s",'
'line="%s",language="%s",context="%s"}'
% (function, fileName, lineNumber, language, context))
fileName = fileNameAsString(lineEntry.file) fileName = fileNameAsString(lineEntry.file)
usable = None
language = None
if False and isNativeMixed:
if self.isReportableInterpreterFrame(functionName):
engine = frame.FindVariable("engine")
self.context = engine
h = self.extractQmlLocation(engine)
pc = 0
functionName = h['function']
fileName = h['file']
lineNumber = h['line']
addr = h['context']
language = 'js'
#elif not functionName is None:
# if functionName.startswith("qt_v4"):
# usable = 0
# elif functionName.find("QV4::") >= 0:
# usable = 0
result += '{pc="0x%x"' % pc result += '{pc="0x%x"' % pc
result += ',level="%d"' % level result += ',level="%d"' % level
result += ',address="0x%x"' % addr result += ',address="0x%x"' % addr
if not usable is None:
result += ',usable="%s"' % usable
result += ',function="%s"' % functionName result += ',function="%s"' % functionName
result += ',line="%d"' % lineNumber result += ',line="%d"' % lineNumber
if not language is None:
result += ',language="%s"' % language
result += ',file="%s"},' % fileName result += ',file="%s"},' % fileName
result += ']' result += ']'
result += ',hasmore="%d"' % isLimited result += ',hasmore="%d"' % isLimited
@@ -1155,16 +1144,28 @@ class Dumper(DumperBase):
with SubItem(self, child): with SubItem(self, child):
self.putItem(child) self.putItem(child)
def reportVariables(self, args): def fetchVariables(self, args):
self.out = "" (ok, res) = self.tryFetchInterpreterVariables(args)
self.reportVariablesHelper(args) if ok:
self.reportResult(self.out, args) self.reportResult(res, args)
def reportVariablesHelper(self, args = {}):
frame = self.currentFrame()
if frame is None:
return return
self.expandedINames = set(args.get('expanded', []))
self.autoDerefPointers = int(args.get('autoderef', '0'))
self.sortStructMembers = bool(args.get('sortStructMembers', True));
self.useDynamicType = int(args.get('dyntype', '0'))
self.useFancy = int(args.get('fancy', '0'))
self.passExceptions = int(args.get('passexceptions', '0'))
self.currentWatchers = args.get('watchers', {})
self.typeformats = args.get("typeformats", {})
self.formats = args.get("formats", {})
frame = self.currentFrame()
if frame is None:
self.reportResult('error="No frame"', args)
return
self.output = ''
partialVariable = args.get("partialVariable", "") partialVariable = args.get("partialVariable", "")
isPartial = len(partialVariable) > 0 isPartial = len(partialVariable) > 0
@@ -1232,6 +1233,7 @@ class Dumper(DumperBase):
self.handleWatches(args) self.handleWatches(args)
self.put('],partial="%d"' % isPartial) self.put('],partial="%d"' % isPartial)
self.reportResult(self.output, args)
def fetchRegisters(self, args = None): def fetchRegisters(self, args = None):
if self.process is None: if self.process is None:
@@ -1281,7 +1283,7 @@ class Dumper(DumperBase):
else: else:
self.isInterrupting_ = True self.isInterrupting_ = True
error = self.process.Stop() error = self.process.Stop()
self.reportResult(describeError(error), args) self.reportResult(self.describeError(error), args)
def detachInferior(self, args): def detachInferior(self, args):
if self.process is None: if self.process is None:
@@ -1330,28 +1332,31 @@ class Dumper(DumperBase):
frame = stoppedThread.GetFrameAtIndex(0) frame = stoppedThread.GetFrameAtIndex(0)
#self.report("FRAME: %s" % frame) #self.report("FRAME: %s" % frame)
function = frame.GetFunction() function = frame.GetFunction()
#self.report("FUNCTION: %s" % function) functionName = function.GetName()
if function.GetName() == "qt_v4ResolvePendingBreakpointsHook": if functionName == "::qt_qmlDebugConnectorOpen()":
#self.report("RESOLVER HIT") self.report("RESOLVER HIT")
for bp in self.qmlBreakpointResolvers: for resolver in self.interpreterBreakpointResolvers:
self.qmlBreakpointResolvers[bp]() resolver()
self.target.BreakpointDelete(bp.GetID()) self.report("AUTO-CONTINUE AFTER RESOLVING")
self.qmlBreakpointResolvers = {} self.reportState("inferiorstopok")
self.process.Continue();
return
if functionName == "::qt_qmlDebugMessageAvailable()":
self.report("ASYNC MESSAGE FROM SERVICE")
res = self.handleInterpreterMessage()
if not res:
self.report("EVENT NEEDS NO STOP")
self.reportState("stopped")
self.process.Continue(); self.process.Continue();
return return
if self.isInterrupting_: if self.isInterrupting_:
self.isInterrupting_ = False self.isInterrupting_ = False
self.reportState("inferiorstopok") self.reportState("stopped")
elif self.ignoreStops > 0: elif self.ignoreStops > 0:
self.ignoreStops -= 1 self.ignoreStops -= 1
self.process.Continue() self.process.Continue()
elif self.silentStops > 0: elif self.silentStops > 0:
self.silentStops -= 1 self.silentStops -= 1
#elif bp and bp in self.qmlBreakpointResolvers:
# self.report("RESOLVER HIT")
# self.qmlBreakpointResolvers[bp]()
# self.process.Continue();
else: else:
self.reportState("stopped") self.reportState("stopped")
else: else:
@@ -1422,7 +1427,7 @@ class Dumper(DumperBase):
if bpType == BreakpointByFileAndLine: if bpType == BreakpointByFileAndLine:
fileName = args["file"] fileName = args["file"]
if fileName.endswith(".js") or fileName.endswith(".qml"): if fileName.endswith(".js") or fileName.endswith(".qml"):
self.doInsertInterpreterBreakpoint(args, False) self.insertInterpreterBreakpoint(args)
return return
extra = '' extra = ''
@@ -1645,19 +1650,6 @@ class Dumper(DumperBase):
error = str(result.GetError()) error = str(result.GetError())
self.report('success="%d",output="%s",error="%s"' % (success, output, error)) self.report('success="%d",output="%s",error="%s"' % (success, output, error))
def fetchLocals(self, args):
self.output = ''
self.expandedINames = set(args.get('expanded', []))
self.autoDerefPointers = int(args.get('autoderef', '0'))
self.sortStructMembers = bool(args.get("sortStructMembers", True));
self.useDynamicType = int(args.get('dyntype', '0'))
self.useFancy = int(args.get('fancy', '0'))
self.passExceptions = int(args.get('passexceptions', '0'))
self.currentWatchers = args.get('watchers', {})
self.typeformats = args.get("typeformats", {})
self.formats = args.get("formats", {})
self.reportVariables(args)
def fetchDisassembler(self, args): def fetchDisassembler(self, args):
functionName = args.get('function', '') functionName = args.get('function', '')
flavor = args.get('flavor', '') flavor = args.get('flavor', '')
@@ -1744,17 +1736,13 @@ class Dumper(DumperBase):
value = self.hexdecode(args['value']) value = self.hexdecode(args['value'])
lhs = self.findValueByExpression(exp) lhs = self.findValueByExpression(exp)
lhs.SetValueFromCString(value, error) lhs.SetValueFromCString(value, error)
self.reportResult(describeError(error), args) self.reportResult(self.describeError(error), args)
def createResolvePendingBreakpointsHookBreakpoint(self, args): def createResolvePendingBreakpointsHookBreakpoint(self, args):
if self.qmlTriggeredBreakpoint is None: bp = self.target.BreakpointCreateByName("qt_qmlDebugConnectorOpen")
self.qmlTriggeredBreakpoint = \
self.target.BreakpointCreateByName("qt_v4TriggeredBreakpointHook")
bp = self.target.BreakpointCreateByName("qt_v4ResolvePendingBreakpointsHook")
bp.SetOneShot(True) bp.SetOneShot(True)
self.qmlBreakpointResolvers[bp] = lambda: \ self.interpreterBreakpointResolvers.append(
self.doInsertQmlBreakpoint(args) lambda: self.resolvePendingInterpreterBreakpoint(args))
# Used in dumper auto test. # Used in dumper auto test.
@@ -1825,7 +1813,7 @@ class Tester(Dumper):
if line != 0: if line != 0:
self.report = savedReport self.report = savedReport
self.process.SetSelectedThread(stoppedThread) self.process.SetSelectedThread(stoppedThread)
self.reportVariables({'token':2}) self.fetchVariables({'token':2, 'fancy':1})
#self.describeLocation(frame) #self.describeLocation(frame)
self.report("@NS@%s@" % self.qtNamespace()) self.report("@NS@%s@" % self.qtNamespace())
#self.report("ENV=%s" % os.environ.items()) #self.report("ENV=%s" % os.environ.items())

View File

@@ -2308,7 +2308,7 @@ def qdump__QV4__String(d, value):
d.putStringValue(d.addressOf(value) + 2 * d.ptrSize()) d.putStringValue(d.addressOf(value) + 2 * d.ptrSize())
def qdump__QV4__Value(d, value): def qdump__QV4__Value(d, value):
v = toInteger(str(value["val"])) v = toInteger(str(value["_val"]))
NaNEncodeMask = 0xffff800000000000 NaNEncodeMask = 0xffff800000000000
IsInt32Mask = 0x0002000000000000 IsInt32Mask = 0x0002000000000000
IsDoubleMask = 0xfffc000000000000 IsDoubleMask = 0xfffc000000000000
@@ -2319,7 +2319,10 @@ def qdump__QV4__Value(d, value):
ns = d.qtNamespace() ns = d.qtNamespace()
if v & IsInt32Mask: if v & IsInt32Mask:
d.putBetterType("%sQV4::Value (int32)" % ns) d.putBetterType("%sQV4::Value (int32)" % ns)
d.putValue(value["int_32"]) vv = v & 0xffffffff
vv = vv if vv < 0x80000000 else -(0x100000000 - vv)
d.putBetterType("%sQV4::Value (int32)" % ns)
d.putValue("%d" % vv)
elif v & IsDoubleMask: elif v & IsDoubleMask:
d.putBetterType("%sQV4::Value (double)" % ns) d.putBetterType("%sQV4::Value (double)" % ns)
d.putValue("%x" % (v ^ 0xffff800000000000), Hex2EncodedFloat8) d.putValue("%x" % (v ^ 0xffff800000000000), Hex2EncodedFloat8)
@@ -2332,6 +2335,7 @@ def qdump__QV4__Value(d, value):
elif v & IsNullOrBooleanMask: elif v & IsNullOrBooleanMask:
d.putBetterType("%sQV4::Value (null/bool)" % ns) d.putBetterType("%sQV4::Value (null/bool)" % ns)
d.putValue("(null/bool)") d.putValue("(null/bool)")
d.putValue(v & 1)
else: else:
vtable = value["m"]["vtable"] vtable = value["m"]["vtable"]
if toInteger(vtable["isString"]): if toInteger(vtable["isString"]):

View File

@@ -53,6 +53,129 @@ public:
$$ $$
} else { } else {
}</snippet> }</snippet>
<snippet group="C++" trigger="lic" id="license-configured" complement="" removed="false" modified="false">%{Cpp:LicenseTemplate}
$$</snippet>
<snippet group="C++" trigger="licbsd" id="license-bsd" complement="" removed="false" modified="false">/**
@if ('%{CurrentProject:Name}' !== '')
** This file is part of the %{CurrentProject:Name} project.
@endif
@if ('%{Env:QTC_COPYRIGHT_USER}' === '' || '%{Env:QTC_COPYRIGHT_EMAIL}' === '')
** Copyright %{CurrentDate:yyyy} $copyright_user$ &lt;$copyright_email$&gt;.
@else
** Copyright %{CurrentDate:yyyy} %{Env:QTC_COPYRIGHT_USER} &lt;%{Env:QTC_COPYRIGHT_EMAIL}&gt;.
@endif
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**
** 1. Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
**
** 2. 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.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
**/
$$</snippet>
<snippet group="C++" trigger="licgpl" id="license-gpl" complement="" removed="false" modified="false">/**
@if ('%{CurrentProject:Name}' !== '')
** This file is part of the %{CurrentProject:Name} project.
@endif
@if ('%{Env:QTC_COPYRIGHT_USER}' === '' || '%{Env:QTC_COPYRIGHT_EMAIL}' === '')
** Copyright %{CurrentDate:yyyy} $copyright_user$ &lt;$copyright_email$&gt;.
@else
** Copyright %{CurrentDate:yyyy} %{Env:QTC_COPYRIGHT_USER} &lt;%{Env:QTC_COPYRIGHT_EMAIL}&gt;.
@endif
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;.
**/
$$</snippet>
<snippet group="C++" trigger="liclgpl" id="license-lgpl" complement="" removed="false" modified="false">/**
@if ('%{CurrentProject:Name}' !== '')
** This file is part of the %{CurrentProject:Name} project.
@endif
@if ('%{Env:QTC_COPYRIGHT_USER}' === '' || '%{Env:QTC_COPYRIGHT_EMAIL}' === '')
** Copyright %{CurrentDate:yyyy} $copyright_user$ &lt;$copyright_email$&gt;.
@else
** Copyright %{CurrentDate:yyyy} %{Env:QTC_COPYRIGHT_USER} &lt;%{Env:QTC_COPYRIGHT_EMAIL}&gt;.
@endif
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;.
**/
$$</snippet>
<snippet group="C++" trigger="licqtc" id="license-qtc" complement="" removed="false" modified="false">/****************************************************************************
**
@if ('%{Env:QTC_COPYRIGHT_USER}' === '' || '%{Env:QTC_COPYRIGHT_EMAIL}' === '')
** Copyright (C) %{CurrentDate:yyyy} $copyright_user$ &lt;$copyright_email$&gt;.
@else
** Copyright (C) %{CurrentDate:yyyy} %{Env:QTC_COPYRIGHT_USER} &lt;%{Env:QTC_COPYRIGHT_EMAIL}&gt;.
@endif
** Contact: http://www.qt.io/licensing
**
** This file is part of %{CurrentProject:Name}
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
$$</snippet>
<snippet group="C++" trigger="namespace" id="cpp_namespace">namespace $name$ { <snippet group="C++" trigger="namespace" id="cpp_namespace">namespace $name$ {
$$ $$
}</snippet> }</snippet>

View File

@@ -0,0 +1,133 @@
%{Cpp:LicenseTemplate}\
#include "%{HdrFileName}"
%{JS: Cpp.openNamespaces('%{Class}')}\
%{CN}::%{CN}(QObject *parent)
: %{Base}(parent)
{
}
@if %{CustomHeader}
QVariant %{CN}::headerData(int section, Qt::Orientation orientation, int role) const
{
// FIXME: Implement me!
}
@if %{Editable}
bool %{CN}::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
{
if (value != headerData(section, orientation, role)) {
// FIXME: Implement me!
emit headerDataChanged(orientation, section, section);
return true;
}
return false;
}
@endif
@endif
QModelIndex %{CN}::index(int row, int column, const QModelIndex &parent) const
{
// FIXME: Implement me!
}
QModelIndex %{CN}::parent(const QModelIndex &index) const
{
// FIXME: Implement me!
}
int %{CN}::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return 0;
// FIXME: Implement me!
}
int %{CN}::columnCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return 0;
// FIXME: Implement me!
}
@if %{DynamicFetch}
bool %{CN}::hasChildren(const QModelIndex &parent) const
{
// FIXME: Implement me!
}
bool %{CN}::canFetchMore(const QModelIndex &parent) const
{
// FIXME: Implement me!
return false;
}
void %{CN}::fetchMore(const QModelIndex &parent)
{
// FIXME: Implement me!
}
@endif
QVariant %{CN}::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
// FIXME: Implement me!
return QVariant();
}
@if %{Editable}
bool %{CN}::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (data(index, role) != value) {
// FIXME: Implement me!
emit dataChanged(index, index, QVector<int>() << role);
return true;
}
return false;
}
Qt::ItemFlags %{CN}::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
return Qt::ItemIsEditable; // FIXME: Implement me!
}
@endif
@if %{AddData}
bool %{CN}::insertRows(int row, int count, const QModelIndex &parent)
{
beginInsertRows(parent, row, row + count - 1);
// FIXME: Implement me!
endInsertRows();
}
bool %{CN}::insertColumns(int column, int count, const QModelIndex &parent)
{
beginInsertColumns(parent, column, column + count - 1);
// FIXME: Implement me!
endInsertColumns();
}
@endif
@if %{RemoveData}
bool %{CN}::removeRows(int row, int count, const QModelIndex &parent)
{
beginRemoveRows(parent, row, row + count - 1);
// FIXME: Implement me!
endRemoveRows();
}
bool %{CN}::removeColumns(int column, int count, const QModelIndex &parent)
{
beginRemoveColumns(parent, column, column + count - 1);
// FIXME: Implement me!
endRemoveColumns();
}
@endif
%{JS: Cpp.closeNamespaces('%{Class}')}\

View File

@@ -0,0 +1,65 @@
%{Cpp:LicenseTemplate}\
#ifndef %{GUARD}
#define %{GUARD}
%{JS: QtSupport.qtIncludes([ 'QtCore/%{Base}' ], [ 'QtCore/%{Base}' ])}\
%{JS: Cpp.openNamespaces('%{Class}')}\
class %{CN} : public %{Base}
{
Q_OBJECT
public:
explicit %{CN}(QObject *parent = 0);
@if %{CustomHeader}
// Header:
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
@if %{Editable}
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override;
@endif
@endif
// Basic functionality:
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
@if %{DynamicFetch}
// Fetch data dynamically:
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
bool canFetchMore(const QModelIndex &parent) const override;
void fetchMore(const QModelIndex &parent) override;
@endif
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@if %{Editable}
// Editable:
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex& index) const override;
@endif
@if %{AddData}
// Add data:
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
@endif
@if %{RemoveData}
// Remove data:
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
@endif
private:
};
%{JS: Cpp.closeNamespaces('%{Class}')}
#endif // %{GUARD}\

View File

@@ -0,0 +1,83 @@
%{Cpp:LicenseTemplate}\
#include "%{HdrFileName}"
%{JS: Cpp.openNamespaces('%{Class}')}\
%{CN}::%{CN}(QObject *parent)
: %{Base}(parent)
{
}
@if %{CustomHeader}
QVariant %{CN}::headerData(int section, Qt::Orientation orientation, int role) const
{
// FIXME: Implement me!
}
@if %{Editable}
bool %{CN}::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
{
if (value != headerData(section, orientation, role)) {
// FIXME: Implement me!
emit headerDataChanged(orientation, section, section);
return true;
}
return false;
}
@endif
@endif
int %{CN}::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return 0;
// FIXME: Implement me!
}
QVariant %{CN}::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
// FIXME: Implement me!
return QVariant();
}
@if %{Editable}
bool %{CN}::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (data(index, role) != value) {
// FIXME: Implement me!
emit dataChanged(index, index, QVector<int>() << role);
return true;
}
return false;
}
Qt::ItemFlags %{CN}::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
return Qt::ItemIsEditable; // FIXME: Implement me!
}
@endif
@if %{AddData}
bool %{CN}::insertRows(int row, int count, const QModelIndex &parent)
{
beginInsertRows(parent, row, row + count - 1);
// FIXME: Implement me!
endInsertRows();
}
@endif
@if %{RemoveData}
bool %{CN}::removeRows(int row, int count, const QModelIndex &parent)
{
beginRemoveRows(parent, row, row + count - 1);
// FIXME: Implement me!
endRemoveRows();
}
@endif
%{JS: Cpp.closeNamespaces('%{Class}')}\

View File

@@ -0,0 +1,50 @@
%{Cpp:LicenseTemplate}\
#ifndef %{GUARD}
#define %{GUARD}
%{JS: QtSupport.qtIncludes([ 'QtCore/%{Base}' ], [ 'QtCore/%{Base}' ])}\
%{JS: Cpp.openNamespaces('%{Class}')}\
class %{CN} : public %{Base}
{
Q_OBJECT
public:
explicit %{CN}(QObject *parent = 0);
@if %{CustomHeader}
// Header:
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
@if %{Editable}
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override;
@endif
@endif
// Basic functionality:
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@if %{Editable}
// Editable:
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex& index) const override;
@endif
@if %{AddData}
// Add data:
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
@endif
@if %{RemoveData}
// Remove data:
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
@endif
private:
};
%{JS: Cpp.closeNamespaces('%{Class}')}
#endif // %{GUARD}\

View File

@@ -0,0 +1,106 @@
%{Cpp:LicenseTemplate}\
#include "%{HdrFileName}"
%{JS: Cpp.openNamespaces('%{Class}')}\
%{CN}::%{CN}(QObject *parent)
: %{Base}(parent)
{
}
@if %{CustomHeader}
QVariant %{CN}::headerData(int section, Qt::Orientation orientation, int role) const
{
// FIXME: Implement me!
}
@if %{Editable}
bool %{CN}::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role)
{
if (value != headerData(section, orientation, role)) {
// FIXME: Implement me!
emit headerDataChanged(orientation, section, section);
return true;
}
return false;
}
@endif
@endif
int %{CN}::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return 0;
// FIXME: Implement me!
}
int %{CN}::columnCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return 0;
// FIXME: Implement me!
}
QVariant %{CN}::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
// FIXME: Implement me!
return QVariant();
}
@if %{Editable}
bool %{CN}::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (data(index, role) != value) {
// FIXME: Implement me!
emit dataChanged(index, index, QVector<int>() << role);
return true;
}
return false;
}
Qt::ItemFlags %{CN}::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
return Qt::ItemIsEditable; // FIXME: Implement me!
}
@endif
@if %{AddData}
bool %{CN}::insertRows(int row, int count, const QModelIndex &parent)
{
beginInsertRows(parent, row, row + count - 1);
// FIXME: Implement me!
endInsertRows();
}
bool %{CN}::insertColumns(int column, int count, const QModelIndex &parent)
{
beginInsertColumns(parent, column, column + count - 1);
// FIXME: Implement me!
endInsertColumns();
}
@endif
@if %{RemoveData}
bool %{CN}::removeRows(int row, int count, const QModelIndex &parent)
{
beginRemoveRows(parent, row, row + count - 1);
// FIXME: Implement me!
endRemoveRows();
}
bool %{CN}::removeColumns(int column, int count, const QModelIndex &parent)
{
beginRemoveColumns(parent, column, column + count - 1);
// FIXME: Implement me!
endRemoveColumns();
}
@endif
%{JS: Cpp.closeNamespaces('%{Class}')}\

View File

@@ -0,0 +1,53 @@
%{Cpp:LicenseTemplate}\
#ifndef %{GUARD}
#define %{GUARD}
%{JS: QtSupport.qtIncludes([ 'QtCore/%{Base}' ], [ 'QtCore/%{Base}' ])}\
%{JS: Cpp.openNamespaces('%{Class}')}\
class %{CN} : public %{Base}
{
Q_OBJECT
public:
explicit %{CN}(QObject *parent = 0);
@if %{CustomHeader}
// Header:
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
@if %{Editable}
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override;
@endif
@endif
// Basic functionality:
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
@if %{Editable}
// Editable:
bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex& index) const override;
@endif
@if %{AddData}
// Add data:
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
@endif
@if %{RemoveData}
// Remove data:
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
@endif
private:
};
%{JS: Cpp.closeNamespaces('%{Class}')}
#endif // %{GUARD}\

View File

@@ -0,0 +1,202 @@
{
"version": 1,
"kind": "file",
"id": "A.ItemView",
"category": "R.Qt",
"trDescription": "Creates a Qt item model.",
"trDisplayName": "Qt Item Model",
"trDisplayCategory": "Qt",
"icon": "../../global/genericfilewizard.png",
"enabled": "%{JS: [ %{Plugins} ].indexOf('CppEditor') >= 0}",
"options":
[
{ "key": "TargetPath", "value": "%{Path}" },
{ "key": "HdrPath", "value": "%{Path}/%{HdrFileName}" },
{ "key": "SrcPath", "value": "%{Path}/%{SrcFileName}" },
{ "key": "CN", "value": "%{JS: Cpp.className('%{Class}')}" },
{ "key": "GUARD", "value": "%{JS: Cpp.classToHeaderGuard('%{Class}', '%{JS: Util.preferredSuffix('text/x-c++hdr')}')}" }
],
"pages":
[
{
"trDisplayName": "Define Item Model Class",
"trShortTitle": "Details",
"typeId": "Fields",
"data" :
[
{
"name": "Class",
"trDisplayName": "Class name:",
"mandatory": true,
"type": "LineEdit",
"data": { "validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)+[a-zA-Z_][a-zA-Z_0-9]*|)" }
},
{
"name": "Base",
"trDisplayName": "Base class:",
"type": "ComboBox",
"data":
{
"items": [ "QAbstractItemModel", "QAbstractTableModel", "QAbstractListModel" ]
}
},
{
"name": "Sp1",
"type": "Spacer",
"data": { "factor": 2 }
},
{
"name": "CustomHeader",
"trDisplayName": "Customize header row",
"type": "CheckBox",
"data": {
"checked": true,
"checkedValue": true,
"uncheckedValue": false
}
},
{
"name": "Editable",
"trDisplayName": "Items are editable",
"type": "CheckBox",
"data": {
"checked": false,
"checkedValue": true,
"uncheckedValue": false
}
},
{
"name": "AddData",
"trDisplayName": "Rows and columns can be added",
"type": "CheckBox",
"data": {
"checked": false,
"checkedValue": true,
"uncheckedValue": false
}
}, {
"name": "RemoveData",
"trDisplayName": "Rows and columns can be removed",
"type": "CheckBox",
"data": {
"checked": false,
"checkedValue": true,
"uncheckedValue": false
}
},
{
"name": "DynamicFetch",
"trDisplayName": "Fetch data dynamically",
"type": "CheckBox",
"data": {
"checked": false,
"checkedValue": true,
"uncheckedValue": false
}
},
{
"name": "HdrFileName",
"type": "LineEdit",
"trDisplayName": "Header file:",
"mandatory": true,
"data": { "trText": "%{JS: Cpp.classToFileName('%{Class}', '%{JS: Util.preferredSuffix('text/x-c++hdr')}')}" }
},
{
"name": "SrcFileName",
"type": "LineEdit",
"trDisplayName": "Source file:",
"mandatory": true,
"data": { "trText": "%{JS: Cpp.classToFileName('%{Class}', '%{JS: Util.preferredSuffix('text/x-c++src')}')}" }
},
{
"name": "Path",
"type": "PathChooser",
"trDisplayName": "Path:",
"mandatory": true,
"data":
{
"kind": "existingDirectory",
"basePath": "%{InitialPath}",
"path": "%{InitialPath}"
}
}
]
},
{
"trDisplayName": "Project Management",
"trShortTitle": "Summary",
"typeId": "Summary"
}
],
"generators":
[
{
"typeId": "File",
"data":
[
{
"source": "itemmodel.h",
"target": "%{HdrPath}",
"condition": "%{JS: '%{Base}' === 'QAbstractItemModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{HdrFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
]
},
{
"source": "itemmodel.cpp",
"target": "%{SrcPath}",
"openInEditor": true,
"condition": "%{JS: '%{Base}' === 'QAbstractItemModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{SrcFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
]
},
{
"source": "tablemodel.h",
"target": "%{HdrPath}",
"condition": "%{JS: '%{Base}' === 'QAbstractTableModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{HdrFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
]
},
{
"source": "tablemodel.cpp",
"target": "%{SrcPath}",
"openInEditor": true,
"condition": "%{JS: '%{Base}' === 'QAbstractTableModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{SrcFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
]
},
{
"source": "listmodel.h",
"target": "%{HdrPath}",
"condition": "%{JS: '%{Base}' === 'QAbstractListModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{HdrFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
]
},
{
"source": "listmodel.cpp",
"target": "%{SrcPath}",
"openInEditor": true,
"condition": "%{JS: '%{Base}' === 'QAbstractListModel'}",
"options": [
{ "key": "Cpp:License:FileName", "value": "%{SrcFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
]
}
]
}
]
}

View File

@@ -1,6 +1,8 @@
QT += core QT += core
QT -= gui QT -= gui
CONFIG += c++11
TARGET = %{ProjectName} TARGET = %{ProjectName}
CONFIG += console CONFIG += console
CONFIG -= app_bundle CONFIG -= app_bundle

View File

@@ -2,6 +2,8 @@ TEMPLATE = app
QT += qml quick QT += qml quick
CONFIG += c++11
SOURCES += main.cpp SOURCES += main.cpp
RESOURCES += qml.qrc RESOURCES += qml.qrc

View File

@@ -6,6 +6,8 @@ QT += qml quick widgets
QT += qml quick QT += qml quick
@endif @endif
CONFIG += c++11
SOURCES += %{MainCppFileName} SOURCES += %{MainCppFileName}
RESOURCES += qml.qrc RESOURCES += qml.qrc

View File

@@ -96,42 +96,35 @@ const char PLUGINPATH_OPTION[] = "-pluginpath";
typedef QList<PluginSpec *> PluginSpecSet; typedef QList<PluginSpec *> PluginSpecSet;
// Helpers for displaying messages. Note that there is no console on Windows. // Helpers for displaying messages. Note that there is no console on Windows.
#ifdef Q_OS_WIN
// Format as <pre> HTML // Format as <pre> HTML
static inline void toHtml(QString &t) static inline QString toHtml(const QString &t)
{ {
t.replace(QLatin1Char('&'), QLatin1String("&amp;")); QString res = t;
t.replace(QLatin1Char('<'), QLatin1String("&lt;")); res.replace(QLatin1Char('&'), QLatin1String("&amp;"));
t.replace(QLatin1Char('>'), QLatin1String("&gt;")); res.replace(QLatin1Char('<'), QLatin1String("&lt;"));
t.insert(0, QLatin1String("<html><pre>")); res.replace(QLatin1Char('>'), QLatin1String("&gt;"));
t.append(QLatin1String("</pre></html>")); res.insert(0, QLatin1String("<html><pre>"));
res.append(QLatin1String("</pre></html>"));
return res;
} }
static void displayHelpText(QString t) // No console on Windows.
{
toHtml(t);
QMessageBox::information(0, QLatin1String(appNameC), t);
}
static void displayError(const QString &t) // No console on Windows.
{
QMessageBox::critical(0, QLatin1String(appNameC), t);
}
#else
static void displayHelpText(const QString &t) static void displayHelpText(const QString &t)
{ {
if (Utils::HostOsInfo::isWindowsHost())
QMessageBox::information(0, QLatin1String(appNameC), toHtml(t));
else
qWarning("%s", qPrintable(t)); qWarning("%s", qPrintable(t));
} }
static void displayError(const QString &t) static void displayError(const QString &t)
{ {
if (Utils::HostOsInfo::isWindowsHost())
QMessageBox::critical(0, QLatin1String(appNameC), t);
else
qCritical("%s", qPrintable(t)); qCritical("%s", qPrintable(t));
} }
#endif
static void printVersion(const PluginSpec *coreplugin) static void printVersion(const PluginSpec *coreplugin)
{ {
QString version; QString version;
@@ -200,19 +193,19 @@ static inline QStringList getPluginPaths()
QDir rootDir = QApplication::applicationDirPath(); QDir rootDir = QApplication::applicationDirPath();
rootDir.cdUp(); rootDir.cdUp();
const QString rootDirPath = rootDir.canonicalPath(); const QString rootDirPath = rootDir.canonicalPath();
#if !defined(Q_OS_MAC) QString pluginPath;
// 1) "plugins" (Win/Linux) if (Utils::HostOsInfo::isMacHost()) {
QString pluginPath = rootDirPath; // 1) "PlugIns" (OS X)
pluginPath = rootDirPath + QLatin1String("/PlugIns");
rc.push_back(pluginPath);
} else {
// 2) "plugins" (Win/Linux)
pluginPath = rootDirPath;
pluginPath += QLatin1Char('/'); pluginPath += QLatin1Char('/');
pluginPath += QLatin1String(IDE_LIBRARY_BASENAME); pluginPath += QLatin1String(IDE_LIBRARY_BASENAME);
pluginPath += QLatin1String("/qtcreator/plugins"); pluginPath += QLatin1String("/qtcreator/plugins");
rc.push_back(pluginPath); rc.push_back(pluginPath);
#else }
// 2) "PlugIns" (OS X)
QString pluginPath = rootDirPath;
pluginPath += QLatin1String("/PlugIns");
rc.push_back(pluginPath);
#endif
// 3) <localappdata>/plugins/<ideversion> // 3) <localappdata>/plugins/<ideversion>
// where <localappdata> is e.g. // where <localappdata> is e.g.
// "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later // "%LOCALAPPDATA%\QtProject\qtcreator" on Windows Vista and later
@@ -225,11 +218,7 @@ static inline QStringList getPluginPaths()
pluginPath += QLatin1Char('/') pluginPath += QLatin1Char('/')
+ QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR) + QLatin1String(Core::Constants::IDE_SETTINGSVARIANT_STR)
+ QLatin1Char('/'); + QLatin1Char('/');
#if !defined(Q_OS_MAC) pluginPath += QLatin1String(Utils::HostOsInfo::isMacHost() ? "Qt Creator" : "qtcreator");
pluginPath += QLatin1String("qtcreator");
#else
pluginPath += QLatin1String("Qt Creator");
#endif
pluginPath += QLatin1String("/plugins/"); pluginPath += QLatin1String("/plugins/");
pluginPath += QLatin1String(Core::Constants::IDE_VERSION_LONG); pluginPath += QLatin1String(Core::Constants::IDE_VERSION_LONG);
rc.push_back(pluginPath); rc.push_back(pluginPath);
@@ -286,11 +275,8 @@ static inline QSettings *userSettings()
return createUserSettings(); return createUserSettings();
} }
#ifdef Q_OS_MAC static const char *SHARE_PATH =
# define SHARE_PATH "/../Resources" Utils::HostOsInfo::isMacHost() ? "/../Resources" : "/../share/qtcreator";
#else
# define SHARE_PATH "/../share/qtcreator"
#endif
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
@@ -391,7 +377,7 @@ int main(int argc, char **argv)
if (!overrideLanguage.isEmpty()) if (!overrideLanguage.isEmpty())
uiLanguages.prepend(overrideLanguage); uiLanguages.prepend(overrideLanguage);
const QString &creatorTrPath = QCoreApplication::applicationDirPath() const QString &creatorTrPath = QCoreApplication::applicationDirPath()
+ QLatin1String(SHARE_PATH "/translations"); + QLatin1String(SHARE_PATH) + QLatin1String("/translations");
foreach (QString locale, uiLanguages) { foreach (QString locale, uiLanguages) {
locale = QLocale(locale).name(); locale = QLocale(locale).name();
if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) { if (translator.load(QLatin1String("qtcreator_") + locale, creatorTrPath)) {

View File

@@ -50,6 +50,7 @@ DObject::DObject()
DObject::DObject(const DObject &rhs) DObject::DObject(const DObject &rhs)
: DElement(rhs), : DElement(rhs),
_model_uid(rhs._model_uid), _model_uid(rhs._model_uid),
_stereotypes(rhs._stereotypes),
_context(rhs._context), _context(rhs._context),
_name(rhs._name), _name(rhs._name),
_pos(rhs._pos), _pos(rhs._pos),
@@ -72,6 +73,7 @@ DObject &DObject::operator =(const DObject &rhs)
if (this != &rhs) { if (this != &rhs) {
DElement::operator=(rhs); DElement::operator=(rhs);
_model_uid = rhs._model_uid; _model_uid = rhs._model_uid;
_stereotypes = rhs._stereotypes;
_context = rhs._context; _context = rhs._context;
_name = rhs._name; _name = rhs._name;
_pos = rhs._pos; _pos = rhs._pos;

View File

@@ -393,7 +393,7 @@ void PropertiesView::MView::visitMElement(const MElement *element)
_stereotype_combo_box = new QComboBox(_top_widget); _stereotype_combo_box = new QComboBox(_top_widget);
_stereotype_combo_box->setEditable(true); _stereotype_combo_box->setEditable(true);
_stereotype_combo_box->setInsertPolicy(QComboBox::NoInsert); _stereotype_combo_box->setInsertPolicy(QComboBox::NoInsert);
_top_layout->addRow(tr("Stereotypes"), _stereotype_combo_box); _top_layout->addRow(tr("Stereotypes:"), _stereotype_combo_box);
_stereotype_combo_box->addItems(_properties_view->getStereotypeController()->getKnownStereotypes(_stereotype_element)); _stereotype_combo_box->addItems(_properties_view->getStereotypeController()->getKnownStereotypes(_stereotype_element));
connect(_stereotype_combo_box->lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onStereotypesChanged(QString))); connect(_stereotype_combo_box->lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onStereotypesChanged(QString)));
connect(_stereotype_combo_box, SIGNAL(activated(QString)), this, SLOT(onStereotypesChanged(QString))); connect(_stereotype_combo_box, SIGNAL(activated(QString)), this, SLOT(onStereotypesChanged(QString)));
@@ -414,7 +414,7 @@ void PropertiesView::MView::visitMElement(const MElement *element)
#ifdef SHOW_DEBUG_PROPERTIES #ifdef SHOW_DEBUG_PROPERTIES
if (_reverse_engineered_label == 0) { if (_reverse_engineered_label == 0) {
_reverse_engineered_label = new QLabel(_top_widget); _reverse_engineered_label = new QLabel(_top_widget);
_top_layout->addRow(tr("Reverese Engineered"), _reverse_engineered_label); _top_layout->addRow(tr("Reverese engineered:"), _reverse_engineered_label);
} }
QString text = element->getFlags().testFlag(MElement::REVERSE_ENGINEERED) ? tr("Yes") : tr("No"); QString text = element->getFlags().testFlag(MElement::REVERSE_ENGINEERED) ? tr("Yes") : tr("No");
_reverse_engineered_label->setText(text); _reverse_engineered_label->setText(text);
@@ -428,7 +428,7 @@ void PropertiesView::MView::visitMObject(const MObject *object)
bool is_single_selection = selection.size() == 1; bool is_single_selection = selection.size() == 1;
if (_element_name_line_edit == 0) { if (_element_name_line_edit == 0) {
_element_name_line_edit = new QLineEdit(_top_widget); _element_name_line_edit = new QLineEdit(_top_widget);
_top_layout->addRow(tr("Name"), _element_name_line_edit); _top_layout->addRow(tr("Name:"), _element_name_line_edit);
connect(_element_name_line_edit, SIGNAL(textChanged(QString)), this, SLOT(onObjectNameChanged(QString))); connect(_element_name_line_edit, SIGNAL(textChanged(QString)), this, SLOT(onObjectNameChanged(QString)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -445,12 +445,12 @@ void PropertiesView::MView::visitMObject(const MObject *object)
#ifdef SHOW_DEBUG_PROPERTIES #ifdef SHOW_DEBUG_PROPERTIES
if (_children_label == 0) { if (_children_label == 0) {
_children_label = new QLabel(_top_widget); _children_label = new QLabel(_top_widget);
_top_layout->addRow(tr("Children"), _children_label); _top_layout->addRow(tr("Children:"), _children_label);
} }
_children_label->setText(QString::number(object->getChildren().size())); _children_label->setText(QString::number(object->getChildren().size()));
if (_relations_label == 0) { if (_relations_label == 0) {
_relations_label = new QLabel(_top_widget); _relations_label = new QLabel(_top_widget);
_top_layout->addRow(tr("Relations"), _relations_label); _top_layout->addRow(tr("Relations:"), _relations_label);
} }
_relations_label->setText(QString::number(object->getRelations().size())); _relations_label->setText(QString::number(object->getRelations().size()));
#endif #endif
@@ -474,7 +474,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
bool is_single_selection = selection.size() == 1; bool is_single_selection = selection.size() == 1;
if (_namespace_line_edit == 0) { if (_namespace_line_edit == 0) {
_namespace_line_edit = new QLineEdit(_top_widget); _namespace_line_edit = new QLineEdit(_top_widget);
_top_layout->addRow(tr("Namespace"), _namespace_line_edit); _top_layout->addRow(tr("Namespace:"), _namespace_line_edit);
connect(_namespace_line_edit, SIGNAL(textEdited(QString)), this, SLOT(onNamespaceChanged(QString))); connect(_namespace_line_edit, SIGNAL(textEdited(QString)), this, SLOT(onNamespaceChanged(QString)));
} }
if (!_namespace_line_edit->hasFocus()) { if (!_namespace_line_edit->hasFocus()) {
@@ -491,7 +491,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
} }
if (_template_parameters_line_edit == 0) { if (_template_parameters_line_edit == 0) {
_template_parameters_line_edit = new QLineEdit(_top_widget); _template_parameters_line_edit = new QLineEdit(_top_widget);
_top_layout->addRow(tr("Template"), _template_parameters_line_edit); _top_layout->addRow(tr("Template:"), _template_parameters_line_edit);
connect(_template_parameters_line_edit, SIGNAL(textChanged(QString)), this, SLOT(onTemplateParametersChanged(QString))); connect(_template_parameters_line_edit, SIGNAL(textChanged(QString)), this, SLOT(onTemplateParametersChanged(QString)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -525,7 +525,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
if (_class_members_edit == 0) { if (_class_members_edit == 0) {
_class_members_edit = new ClassMembersEdit(_top_widget); _class_members_edit = new ClassMembersEdit(_top_widget);
_class_members_edit->setLineWrapMode(QPlainTextEdit::NoWrap); _class_members_edit->setLineWrapMode(QPlainTextEdit::NoWrap);
_top_layout->addRow(tr("Members"), _class_members_edit); _top_layout->addRow(tr("Members:"), _class_members_edit);
connect(_class_members_edit, SIGNAL(membersChanged(QList<MClassMember>&)), this, SLOT(onClassMembersChanged(QList<MClassMember>&))); connect(_class_members_edit, SIGNAL(membersChanged(QList<MClassMember>&)), this, SLOT(onClassMembersChanged(QList<MClassMember>&)));
connect(_class_members_edit, SIGNAL(statusChanged(bool)), this, SLOT(onClassMembersStatusChanged(bool))); connect(_class_members_edit, SIGNAL(statusChanged(bool)), this, SLOT(onClassMembersStatusChanged(bool)));
} }
@@ -554,7 +554,7 @@ void PropertiesView::MView::visitMDiagram(const MDiagram *diagram)
#ifdef SHOW_DEBUG_PROPERTIES #ifdef SHOW_DEBUG_PROPERTIES
if (_diagrams_label == 0) { if (_diagrams_label == 0) {
_diagrams_label = new QLabel(_top_widget); _diagrams_label = new QLabel(_top_widget);
_top_layout->addRow(tr("Elements"), _diagrams_label); _top_layout->addRow(tr("Elements:"), _diagrams_label);
} }
_diagrams_label->setText(QString::number(diagram->getDiagramElements().size())); _diagrams_label->setText(QString::number(diagram->getDiagramElements().size()));
#endif #endif
@@ -575,7 +575,7 @@ void PropertiesView::MView::visitMItem(const MItem *item)
if (item->isVarietyEditable()) { if (item->isVarietyEditable()) {
if (_item_variety_edit == 0) { if (_item_variety_edit == 0) {
_item_variety_edit = new QLineEdit(_top_widget); _item_variety_edit = new QLineEdit(_top_widget);
_top_layout->addRow(tr("Variety"), _item_variety_edit); _top_layout->addRow(tr("Variety:"), _item_variety_edit);
connect(_item_variety_edit, SIGNAL(textChanged(QString)), this, SLOT(onItemVarietyChanged(QString))); connect(_item_variety_edit, SIGNAL(textChanged(QString)), this, SLOT(onItemVarietyChanged(QString)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -598,7 +598,7 @@ void PropertiesView::MView::visitMRelation(const MRelation *relation)
bool is_single_selection = selection.size() == 1; bool is_single_selection = selection.size() == 1;
if (_element_name_line_edit == 0) { if (_element_name_line_edit == 0) {
_element_name_line_edit = new QLineEdit(_top_widget); _element_name_line_edit = new QLineEdit(_top_widget);
_top_layout->addRow(tr("Name"), _element_name_line_edit); _top_layout->addRow(tr("Name:"), _element_name_line_edit);
connect(_element_name_line_edit, SIGNAL(textChanged(QString)), this, SLOT(onRelationNameChanged(QString))); connect(_element_name_line_edit, SIGNAL(textChanged(QString)), this, SLOT(onRelationNameChanged(QString)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -628,7 +628,7 @@ void PropertiesView::MView::visitMDependency(const MDependency *dependency)
if (_direction_selector == 0) { if (_direction_selector == 0) {
_direction_selector = new QComboBox(_top_widget); _direction_selector = new QComboBox(_top_widget);
_direction_selector->addItems(QStringList() << QStringLiteral("->") << QStringLiteral("<-") << QStringLiteral("<->")); _direction_selector->addItems(QStringList() << QStringLiteral("->") << QStringLiteral("<-") << QStringLiteral("<->"));
_top_layout->addRow(tr("Direction"), _direction_selector); _top_layout->addRow(tr("Direction:"), _direction_selector);
connect(_direction_selector, SIGNAL(activated(int)), this, SLOT(onDependencyDirectionChanged(int))); connect(_direction_selector, SIGNAL(activated(int)), this, SLOT(onDependencyDirectionChanged(int)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -649,9 +649,9 @@ void PropertiesView::MView::visitMInheritance(const MInheritance *inheritance)
setTitle<MInheritance>(_model_elements, tr("Inheritance"), tr("Inheritances")); setTitle<MInheritance>(_model_elements, tr("Inheritance"), tr("Inheritances"));
MObject *derived_class = _properties_view->getModelController()->findObject(inheritance->getDerived()); MObject *derived_class = _properties_view->getModelController()->findObject(inheritance->getDerived());
QMT_CHECK(derived_class); QMT_CHECK(derived_class);
setEndAName(tr("Derived Class: %1").arg(derived_class->getName())); setEndAName(tr("Derived class: %1").arg(derived_class->getName()));
MObject *base_class = _properties_view->getModelController()->findObject(inheritance->getBase()); MObject *base_class = _properties_view->getModelController()->findObject(inheritance->getBase());
setEndBName(tr("Base Class: %1").arg(base_class->getName())); setEndBName(tr("Base class: %1").arg(base_class->getName()));
visitMRelation(inheritance); visitMRelation(inheritance);
} }
@@ -667,7 +667,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
} }
if (_end_a_end_name == 0) { if (_end_a_end_name == 0) {
_end_a_end_name = new QLineEdit(_top_widget); _end_a_end_name = new QLineEdit(_top_widget);
_top_layout->addRow(tr("Role"), _end_a_end_name); _top_layout->addRow(tr("Role:"), _end_a_end_name);
connect(_end_a_end_name, SIGNAL(textChanged(QString)), this, SLOT(onAssociationEndANameChanged(QString))); connect(_end_a_end_name, SIGNAL(textChanged(QString)), this, SLOT(onAssociationEndANameChanged(QString)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -682,7 +682,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
} }
if (_end_a_cardinality == 0) { if (_end_a_cardinality == 0) {
_end_a_cardinality = new QLineEdit(_top_widget); _end_a_cardinality = new QLineEdit(_top_widget);
_top_layout->addRow(tr("Cardinality"), _end_a_cardinality); _top_layout->addRow(tr("Cardinality:"), _end_a_cardinality);
connect(_end_a_cardinality, SIGNAL(textChanged(QString)), this, SLOT(onAssociationEndACardinalityChanged(QString))); connect(_end_a_cardinality, SIGNAL(textChanged(QString)), this, SLOT(onAssociationEndACardinalityChanged(QString)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -713,7 +713,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
if (_end_a_kind == 0) { if (_end_a_kind == 0) {
_end_a_kind = new QComboBox(_top_widget); _end_a_kind = new QComboBox(_top_widget);
_end_a_kind->addItems(QStringList() << tr("Association") << tr("Aggregation") << tr("Composition")); _end_a_kind->addItems(QStringList() << tr("Association") << tr("Aggregation") << tr("Composition"));
_top_layout->addRow(tr("Relationship"), _end_a_kind); _top_layout->addRow(tr("Relationship:"), _end_a_kind);
connect(_end_a_kind, SIGNAL(activated(int)), this, SLOT(onAssociationEndAKindChanged(int))); connect(_end_a_kind, SIGNAL(activated(int)), this, SLOT(onAssociationEndAKindChanged(int)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -734,7 +734,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
} }
if (_end_b_end_name == 0) { if (_end_b_end_name == 0) {
_end_b_end_name = new QLineEdit(_top_widget); _end_b_end_name = new QLineEdit(_top_widget);
_top_layout->addRow(tr("Role"), _end_b_end_name); _top_layout->addRow(tr("Role:"), _end_b_end_name);
connect(_end_b_end_name, SIGNAL(textChanged(QString)), this, SLOT(onAssociationEndBNameChanged(QString))); connect(_end_b_end_name, SIGNAL(textChanged(QString)), this, SLOT(onAssociationEndBNameChanged(QString)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -749,7 +749,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
} }
if (_end_b_cardinality == 0) { if (_end_b_cardinality == 0) {
_end_b_cardinality = new QLineEdit(_top_widget); _end_b_cardinality = new QLineEdit(_top_widget);
_top_layout->addRow(tr("Cardinality"), _end_b_cardinality); _top_layout->addRow(tr("Cardinality:"), _end_b_cardinality);
connect(_end_b_cardinality, SIGNAL(textChanged(QString)), this, SLOT(onAssociationEndBCardinalityChanged(QString))); connect(_end_b_cardinality, SIGNAL(textChanged(QString)), this, SLOT(onAssociationEndBCardinalityChanged(QString)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -780,7 +780,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
if (_end_b_kind == 0) { if (_end_b_kind == 0) {
_end_b_kind = new QComboBox(_top_widget); _end_b_kind = new QComboBox(_top_widget);
_end_b_kind->addItems(QStringList() << tr("Association") << tr("Aggregation") << tr("Composition")); _end_b_kind->addItems(QStringList() << tr("Association") << tr("Aggregation") << tr("Composition"));
_top_layout->addRow(tr("Relationship"), _end_b_kind); _top_layout->addRow(tr("Relationship:"), _end_b_kind);
connect(_end_b_kind, SIGNAL(activated(int)), this, SLOT(onAssociationEndBKindChanged(int))); connect(_end_b_kind, SIGNAL(activated(int)), this, SLOT(onAssociationEndBKindChanged(int)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -823,7 +823,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
#ifdef SHOW_DEBUG_PROPERTIES #ifdef SHOW_DEBUG_PROPERTIES
if (_pos_rect_label == 0) { if (_pos_rect_label == 0) {
_pos_rect_label = new QLabel(_top_widget); _pos_rect_label = new QLabel(_top_widget);
_top_layout->addRow(tr("Pos&Size"), _pos_rect_label); _top_layout->addRow(tr("Position and size:"), _pos_rect_label);
} }
_pos_rect_label->setText(QString(QStringLiteral("(%1,%2):(%3,%4)-(%5,%6)")) _pos_rect_label->setText(QString(QStringLiteral("(%1,%2):(%3,%4)-(%5,%6)"))
.arg(object->getPos().x()) .arg(object->getPos().x())
@@ -835,7 +835,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
#endif #endif
if (_auto_sized_checkbox == 0) { if (_auto_sized_checkbox == 0) {
_auto_sized_checkbox = new QCheckBox(_top_widget); _auto_sized_checkbox = new QCheckBox(_top_widget);
_top_layout->addRow(tr("Auto Sized"), _auto_sized_checkbox); _top_layout->addRow(tr("Auto sized"), _auto_sized_checkbox);
connect(_auto_sized_checkbox, SIGNAL(clicked(bool)), this, SLOT(onAutoSizedChanged(bool))); connect(_auto_sized_checkbox, SIGNAL(clicked(bool)), this, SLOT(onAutoSizedChanged(bool)));
} }
if (!_auto_sized_checkbox->hasFocus()) { if (!_auto_sized_checkbox->hasFocus()) {
@@ -853,7 +853,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
setPrimaryRolePalette(_style_element_type, DObject::PRIMARY_ROLE_CUSTOM3, QColor()); setPrimaryRolePalette(_style_element_type, DObject::PRIMARY_ROLE_CUSTOM3, QColor());
setPrimaryRolePalette(_style_element_type, DObject::PRIMARY_ROLE_CUSTOM4, QColor()); setPrimaryRolePalette(_style_element_type, DObject::PRIMARY_ROLE_CUSTOM4, QColor());
setPrimaryRolePalette(_style_element_type, DObject::PRIMARY_ROLE_CUSTOM5, QColor()); setPrimaryRolePalette(_style_element_type, DObject::PRIMARY_ROLE_CUSTOM5, QColor());
_top_layout->addRow(QStringLiteral("Color"), _visual_primary_role_selector); _top_layout->addRow(tr("Color:"), _visual_primary_role_selector);
connect(_visual_primary_role_selector, SIGNAL(activated(int)), this, SLOT(onVisualPrimaryRoleChanged(int))); connect(_visual_primary_role_selector, SIGNAL(activated(int)), this, SLOT(onVisualPrimaryRoleChanged(int)));
} }
if (!_visual_primary_role_selector->hasFocus()) { if (!_visual_primary_role_selector->hasFocus()) {
@@ -880,7 +880,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
_visual_secondary_role_selector->addItems(QStringList() << tr("Normal") _visual_secondary_role_selector->addItems(QStringList() << tr("Normal")
<< tr("Lighter") << tr("Darker") << tr("Lighter") << tr("Darker")
<< tr("Soften") << tr("Outline")); << tr("Soften") << tr("Outline"));
_top_layout->addRow(tr("Role"), _visual_secondary_role_selector); _top_layout->addRow(tr("Role:"), _visual_secondary_role_selector);
connect(_visual_secondary_role_selector, SIGNAL(activated(int)), this, SLOT(onVisualSecondaryRoleChanged(int))); connect(_visual_secondary_role_selector, SIGNAL(activated(int)), this, SLOT(onVisualSecondaryRoleChanged(int)));
} }
if (!_visual_secondary_role_selector->hasFocus()) { if (!_visual_secondary_role_selector->hasFocus()) {
@@ -908,7 +908,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
_stereotype_display_selector = new QComboBox(_top_widget); _stereotype_display_selector = new QComboBox(_top_widget);
_stereotype_display_selector->addItems(QStringList() << tr("Smart") << tr("None") << tr("Label") _stereotype_display_selector->addItems(QStringList() << tr("Smart") << tr("None") << tr("Label")
<< tr("Decoration") << tr("Icon")); << tr("Decoration") << tr("Icon"));
_top_layout->addRow(tr("Stereotype Display"), _stereotype_display_selector); _top_layout->addRow(tr("Stereotype display:"), _stereotype_display_selector);
connect(_stereotype_display_selector, SIGNAL(activated(int)), this, SLOT(onStereotypeDisplayChanged(int))); connect(_stereotype_display_selector, SIGNAL(activated(int)), this, SLOT(onStereotypeDisplayChanged(int)));
} }
if (!_stereotype_display_selector->hasFocus()) { if (!_stereotype_display_selector->hasFocus()) {
@@ -922,7 +922,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
#ifdef SHOW_DEBUG_PROPERTIES #ifdef SHOW_DEBUG_PROPERTIES
if (_depth_label == 0) { if (_depth_label == 0) {
_depth_label = new QLabel(_top_widget); _depth_label = new QLabel(_top_widget);
_top_layout->addRow(tr("Depth"), _depth_label); _top_layout->addRow(tr("Depth:"), _depth_label);
} }
_depth_label->setText(QString::number(object->getDepth())); _depth_label->setText(QString::number(object->getDepth()));
#endif #endif
@@ -945,7 +945,7 @@ void PropertiesView::MView::visitDClass(const DClass *klass)
if (_template_display_selector == 0) { if (_template_display_selector == 0) {
_template_display_selector = new QComboBox(_top_widget); _template_display_selector = new QComboBox(_top_widget);
_template_display_selector->addItems(QStringList() << tr("Smart") << tr("Box") << tr("Angle Brackets")); _template_display_selector->addItems(QStringList() << tr("Smart") << tr("Box") << tr("Angle Brackets"));
_top_layout->addRow(tr("Template Display"), _template_display_selector); _top_layout->addRow(tr("Template display:"), _template_display_selector);
connect(_template_display_selector, SIGNAL(activated(int)), this, SLOT(onTemplateDisplayChanged(int))); connect(_template_display_selector, SIGNAL(activated(int)), this, SLOT(onTemplateDisplayChanged(int)));
} }
if (!_template_display_selector->hasFocus()) { if (!_template_display_selector->hasFocus()) {
@@ -958,7 +958,7 @@ void PropertiesView::MView::visitDClass(const DClass *klass)
} }
if (_show_all_members_checkbox == 0) { if (_show_all_members_checkbox == 0) {
_show_all_members_checkbox = new QCheckBox(_top_widget); _show_all_members_checkbox = new QCheckBox(_top_widget);
_top_layout->addRow(tr("Show Members"), _show_all_members_checkbox); _top_layout->addRow(tr("Show members"), _show_all_members_checkbox);
connect(_show_all_members_checkbox, SIGNAL(clicked(bool)), this, SLOT(onShowAllMembersChanged(bool))); connect(_show_all_members_checkbox, SIGNAL(clicked(bool)), this, SLOT(onShowAllMembersChanged(bool)));
} }
if (!_show_all_members_checkbox->hasFocus()) { if (!_show_all_members_checkbox->hasFocus()) {
@@ -979,7 +979,7 @@ void PropertiesView::MView::visitDComponent(const DComponent *component)
visitDObject(component); visitDObject(component);
if (_plain_shape_checkbox == 0) { if (_plain_shape_checkbox == 0) {
_plain_shape_checkbox = new QCheckBox(_top_widget); _plain_shape_checkbox = new QCheckBox(_top_widget);
_top_layout->addRow(tr("Plain Shape"), _plain_shape_checkbox); _top_layout->addRow(tr("Plain shape"), _plain_shape_checkbox);
connect(_plain_shape_checkbox, SIGNAL(clicked(bool)), this, SLOT(onPlainShapeChanged(bool))); connect(_plain_shape_checkbox, SIGNAL(clicked(bool)), this, SLOT(onPlainShapeChanged(bool)));
} }
if (!_plain_shape_checkbox->hasFocus()) { if (!_plain_shape_checkbox->hasFocus()) {
@@ -1010,7 +1010,7 @@ void PropertiesView::MView::visitDItem(const DItem *item)
if (item->isShapeEditable()) { if (item->isShapeEditable()) {
if (_item_shape_edit == 0) { if (_item_shape_edit == 0) {
_item_shape_edit = new QLineEdit(_top_widget); _item_shape_edit = new QLineEdit(_top_widget);
_top_layout->addRow(tr("Shape"), _item_shape_edit); _top_layout->addRow(tr("Shape:"), _item_shape_edit);
connect(_item_shape_edit, SIGNAL(textChanged(QString)), this, SLOT(onItemShapeChanged(QString))); connect(_item_shape_edit, SIGNAL(textChanged(QString)), this, SLOT(onItemShapeChanged(QString)));
} }
if (is_single_selection) { if (is_single_selection) {
@@ -1055,7 +1055,7 @@ void PropertiesView::MView::visitDAnnotation(const DAnnotation *annotation)
visitDElement(annotation); visitDElement(annotation);
if (_annotation_auto_width_checkbox == 0) { if (_annotation_auto_width_checkbox == 0) {
_annotation_auto_width_checkbox = new QCheckBox(_top_widget); _annotation_auto_width_checkbox = new QCheckBox(_top_widget);
_top_layout->addRow(tr("Auto Width"), _annotation_auto_width_checkbox); _top_layout->addRow(tr("Auto width"), _annotation_auto_width_checkbox);
connect(_annotation_auto_width_checkbox, SIGNAL(clicked(bool)), this, SLOT(onAutoWidthChanged(bool))); connect(_annotation_auto_width_checkbox, SIGNAL(clicked(bool)), this, SLOT(onAutoWidthChanged(bool)));
} }
if (!_annotation_auto_width_checkbox->hasFocus()) { if (!_annotation_auto_width_checkbox->hasFocus()) {
@@ -1069,7 +1069,7 @@ void PropertiesView::MView::visitDAnnotation(const DAnnotation *annotation)
if (_annotation_visual_role_selector == 0) { if (_annotation_visual_role_selector == 0) {
_annotation_visual_role_selector = new QComboBox(_top_widget); _annotation_visual_role_selector = new QComboBox(_top_widget);
_annotation_visual_role_selector->addItems(QStringList() << tr("Normal") << tr("Title") << tr("Subtitle") << tr("Emphasized") << tr("Soften") << tr("Footnote")); _annotation_visual_role_selector->addItems(QStringList() << tr("Normal") << tr("Title") << tr("Subtitle") << tr("Emphasized") << tr("Soften") << tr("Footnote"));
_top_layout->addRow(tr("Role"), _annotation_visual_role_selector); _top_layout->addRow(tr("Role:"), _annotation_visual_role_selector);
connect(_annotation_visual_role_selector, SIGNAL(activated(int)), this, SLOT(onAnnotationVisualRoleChanged(int))); connect(_annotation_visual_role_selector, SIGNAL(activated(int)), this, SLOT(onAnnotationVisualRoleChanged(int)));
} }
if (!_annotation_visual_role_selector->hasFocus()) { if (!_annotation_visual_role_selector->hasFocus()) {

View File

@@ -125,7 +125,6 @@ HEADERS += \
$$PWD/model_widgets_ui/propertiesviewmview.h \ $$PWD/model_widgets_ui/propertiesviewmview.h \
$$PWD/project_controller/projectcontroller.h \ $$PWD/project_controller/projectcontroller.h \
$$PWD/project/project.h \ $$PWD/project/project.h \
$$PWD/serializer/diagramreferenceserializer.h \
$$PWD/serializer/diagramserializer.h \ $$PWD/serializer/diagramserializer.h \
$$PWD/serializer/infrastructureserializer.h \ $$PWD/serializer/infrastructureserializer.h \
$$PWD/serializer/modelserializer.h \ $$PWD/serializer/modelserializer.h \
@@ -253,7 +252,6 @@ SOURCES += \
$$PWD/model_widgets_ui/propertiesviewmview.cpp \ $$PWD/model_widgets_ui/propertiesviewmview.cpp \
$$PWD/project_controller/projectcontroller.cpp \ $$PWD/project_controller/projectcontroller.cpp \
$$PWD/project/project.cpp \ $$PWD/project/project.cpp \
$$PWD/serializer/diagramreferenceserializer.cpp \
$$PWD/serializer/diagramserializer.cpp \ $$PWD/serializer/diagramserializer.cpp \
$$PWD/serializer/infrastructureserializer.cpp \ $$PWD/serializer/infrastructureserializer.cpp \
$$PWD/serializer/modelserializer.cpp \ $$PWD/serializer/modelserializer.cpp \

View File

@@ -1,152 +0,0 @@
/***************************************************************************
**
** Copyright (C) 2015 Jochen Becher
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "diagramreferenceserializer.h"
#include "infrastructureserializer.h"
#include "qmt/project/project.h"
#include "qmt/model/mdiagram.h"
#include "qark/qxmloutarchive.h"
#include "qark/qxmlinarchive.h"
#include "qark/serialize.h"
#include "qmt/infrastructure/ioexceptions.h"
#include <QFile>
namespace qark {
using namespace qmt;
QARK_REGISTER_TYPE_NAME(DiagramReferenceSerializer::Reference, "DiagramReferenceSerializer--Reference")
template<class Archive>
void serialize(Archive &archive, DiagramReferenceSerializer::Reference &reference)
{
archive || qark::tag(QStringLiteral("diagram-reference"), reference)
|| qark::attr(QStringLiteral("model"), reference._model_uid)
|| qark::attr(QStringLiteral("diagram"), reference._diagram_uid)
|| qark::end;
}
}
namespace qmt {
DiagramReferenceSerializer::Reference::Reference()
{
}
DiagramReferenceSerializer::Reference::Reference(const Uid &model_uid, const Uid &diagram_uid)
: _model_uid(model_uid),
_diagram_uid(diagram_uid)
{
}
DiagramReferenceSerializer::DiagramReferenceSerializer()
{
}
DiagramReferenceSerializer::~DiagramReferenceSerializer()
{
}
void DiagramReferenceSerializer::save(const QString &file_name, const DiagramReferenceSerializer::Reference &reference)
{
QFile file(file_name);
if (!file.open(QIODevice::WriteOnly)) {
throw FileCreationException(file_name);
}
QIODevice *xml_device = &file;
QXmlStreamWriter writer(xml_device);
write(reference, &writer);
}
QByteArray DiagramReferenceSerializer::save(const Project *project, const MDiagram *diagram)
{
QByteArray buffer;
QXmlStreamWriter writer(&buffer);
write(Reference(project->getUid(), diagram->getUid()), &writer);
return buffer;
}
DiagramReferenceSerializer::Reference DiagramReferenceSerializer::load(const QString &file_name)
{
QFile file(file_name);
if (!file.open(QIODevice::ReadOnly)) {
throw FileNotFoundException(file_name);
}
QIODevice *xml_device = &file;
QXmlStreamReader reader(xml_device);
return read(&reader);
}
DiagramReferenceSerializer::Reference DiagramReferenceSerializer::load(const QByteArray &contents)
{
QXmlStreamReader reader(contents);
return read(&reader);
}
void DiagramReferenceSerializer::write(const Reference &reference, QXmlStreamWriter *writer)
{
writer->setAutoFormatting(true);
writer->setAutoFormattingIndent(2);
qark::QXmlOutArchive archive(*writer);
archive.beginDocument();
archive << qark::tag("qmt-diagram-reference");
archive << reference;
archive << qark::end();
archive.endDocument();
}
DiagramReferenceSerializer::Reference DiagramReferenceSerializer::read(QXmlStreamReader *stream_reader)
{
Reference reference;
qark::QXmlInArchive archive(*stream_reader);
archive.beginDocument();
archive >> qark::tag("qmt-diagram-reference");
archive >> reference;
archive >> qark::end;
archive.endDocument();
return reference;
}
}

View File

@@ -55,12 +55,24 @@ void save(Archive &archive, const T &t)
Access<Archive, T>::save(archive, t); Access<Archive, T>::save(archive, t);
} }
template<class Archive, class T>
void save(Archive &archive, const T &t, const Parameters &)
{
save(archive, t);
}
template<class Archive, class T> template<class Archive, class T>
void load(Archive &archive, T &t) void load(Archive &archive, T &t)
{ {
Access<Archive, T>::load(archive, t); Access<Archive, T>::load(archive, t);
} }
template<class Archive, class T>
void load(Archive &archive, T &t, const Parameters &)
{
load(archive, t);
}
template<class Archive, class T> template<class Archive, class T>
void serialize(Archive &archive, T &t) void serialize(Archive &archive, T &t)
{ {
@@ -92,30 +104,9 @@ void serialize_helper(Archive &archive, T &t)
static inline void serialize(Archive &archive, TYPE &); \ static inline void serialize(Archive &archive, TYPE &); \
}; };
#if 0
#define QARK_ACCESS_SPECIALIZE_LOAD_SAVE(INARCHIVE, OUTARCHIVE, TYPE) \
template<> class Access<INARCHIVE, TYPE> { public: static inline void load(INARCHIVE &archive, TYPE &); void serialize(INARCHIVE &, TYPE &); }; \
template<> class Access<OUTARCHIVE, TYPE> { public: static inline void save(OUTARCHIVE &archive, const TYPE &); void serialize(OUTARCHIVE &, TYPE &); }; \
void Access<INARCHIVE, TYPE>::serialize(INARCHIVE &, TYPE &) { } \
void Access<OUTARCHIVE, TYPE>::serialize(OUTARCHIVE &, TYPE &) { } \
template class Access<INARCHIVE, TYPE>; \
template class Access<OUTARCHIVE, TYPE>;
#endif
#define QARK_ACCESS_SPECIALIZE(INARCHIVE, OUTARCHIVE, TYPE) \ #define QARK_ACCESS_SPECIALIZE(INARCHIVE, OUTARCHIVE, TYPE) \
template class Access<INARCHIVE, TYPE>; \ template class Access<INARCHIVE, TYPE>; \
template class Access<OUTARCHIVE, TYPE>; template class Access<OUTARCHIVE, TYPE>;
#if 0
#define QARK_SPECIALIZE_SERIALIZE(INARCHIVE, OUTARCHIVE, TYPE) \
QARK_ACCESS_SPECIALIZE(INARCHIVE, OUTARCHIVE, TYPE); \
template void serialize<INARCHIVE, TYPE>(INARCHIVE &, TYPE &); \
template void serialize<OUTARCHIVE, TYPE>(OUTARCHIVE &, TYPE &);
#define QARK_SPECIALIZE_LOAD_SAVE(INARCHIVE, OUTARCHIVE, TYPE) \
template void load<INARCHIVE, TYPE>(INARCHIVE &, TYPE &); \
template void save<OUTARCHIVE, TYPE>(OUTARCHIVE &, const TYPE &);
#endif
#endif // QARK_ACCESS_H #endif // QARK_ACCESS_H

View File

@@ -33,6 +33,10 @@
#include "flag.h" #include "flag.h"
#include <QVariant>
#include <QString>
#include <QHash>
namespace qark { namespace qark {
class ArchiveBasics class ArchiveBasics
@@ -48,8 +52,40 @@ public:
bool takeFlag(const Flag &flag) { bool f = (_flags & flag.getMask()) != 0; _flags &= ~flag.getMask(); return f; } bool takeFlag(const Flag &flag) { bool f = (_flags & flag.getMask()) != 0; _flags &= ~flag.getMask(); return f; }
bool hasUserData(const QString &key)
{
return _user_data.contains(key);
}
template<typename T>
T getUserData(const QString &key)
{
return _user_data.value(key).value<T>();
}
template<typename T>
T getUserData(const QString &key, const T &default_value)
{
// gcc 4.8.2 fails to compile if the following 2 statements are written in one expression
//return _user_data.value(key, data).value<T>();
QVariant v = _user_data.value(key, default_value);
return v.value<T>();
}
template<class T>
void setUserData(const QString &key, const T &data)
{
_user_data.insert(key, data);
}
void removeUserData(const QString &key)
{
_user_data.remove(key);
}
private: private:
Flag::mask_type _flags; Flag::mask_type _flags;
QHash<QString, QVariant> _user_data;
}; };
} }

View File

@@ -31,6 +31,8 @@
#ifndef QARK_ATTRIBUTE_H #ifndef QARK_ATTRIBUTE_H
#define QARK_ATTRIBUTE_H #define QARK_ATTRIBUTE_H
#include "parameters.h"
#include <QString> #include <QString>
namespace qark { namespace qark {
@@ -38,19 +40,29 @@ namespace qark {
template<typename T> template<typename T>
class Attr { class Attr {
public: public:
explicit Attr(const QString &qualified_name, T *value) Attr(const QString &qualified_name, T *value)
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_value(value) _value(value)
{ {
} }
Attr(const QString &qualified_name, T *value, const Parameters &parameters)
: _qualified_name(qualified_name),
_value(value),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
T *getValue() const { return _value; } T *getValue() const { return _value; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
T *_value; T *_value;
Parameters _parameters;
}; };
template<typename T> template<typename T>
@@ -59,33 +71,56 @@ Attr<T * const> attr(const QString &qualified_name, T * const &value)
return Attr<T * const>(qualified_name, &value); return Attr<T * const>(qualified_name, &value);
} }
template<typename T>
Attr<T * const> attr(const QString &qualified_name, T * const &value, const Parameters &parameters)
{
return Attr<T * const>(qualified_name, &value, parameters);
}
template<typename T> template<typename T>
Attr<T> attr(const QString &qualified_name, T &value) Attr<T> attr(const QString &qualified_name, T &value)
{ {
return Attr<T>(qualified_name, &value); return Attr<T>(qualified_name, &value);
} }
template<typename T>
Attr<T> attr(const QString &qualified_name, T &value, const Parameters &parameters)
{
return Attr<T>(qualified_name, &value, parameters);
}
template<class U, typename T> template<class U, typename T>
class GetterAttr { class GetterAttr {
public: public:
explicit GetterAttr(const QString &qualified_name, const U &u, T (U::*getter)() const) GetterAttr(const QString &qualified_name, const U &u, T (U::*getter)() const)
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_getter(getter) _getter(getter)
{ {
} }
GetterAttr(const QString &qualified_name, const U &u, T (U::*getter)() const, const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_getter(getter),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
const U &getObject() const { return _u; } const U &getObject() const { return _u; }
T (U::*getGetter() const)() const { return _getter; } T (U::*getGetter() const)() const { return _getter; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
const U &_u; const U &_u;
T (U::*_getter)() const; T (U::*_getter)() const;
Parameters _parameters;
}; };
template<class U, typename T> template<class U, typename T>
@@ -94,27 +129,44 @@ GetterAttr<U, T> attr(const QString &qualified_name, const U &u, T (U::*getter)(
return GetterAttr<U, T>(qualified_name, u, getter); return GetterAttr<U, T>(qualified_name, u, getter);
} }
template<class U, typename T>
GetterAttr<U, T> attr(const QString &qualified_name, const U &u, T (U::*getter)() const, const Parameters &parameters)
{
return GetterAttr<U, T>(qualified_name, u, getter, parameters);
}
template<class U, typename T> template<class U, typename T>
class SetterAttr { class SetterAttr {
public: public:
explicit SetterAttr(const QString &qualified_name, U &u, void (U::*setter)(T)) SetterAttr(const QString &qualified_name, U &u, void (U::*setter)(T))
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_setter(setter) _setter(setter)
{ {
} }
SetterAttr(const QString &qualified_name, U &u, void (U::*setter)(T), const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_setter(setter),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
U &getObject() const { return _u; } U &getObject() const { return _u; }
void (U::*getSetter() const)(T) { return _setter; } void (U::*getSetter() const)(T) { return _setter; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
U &_u; U &_u;
void (U::*_setter)(T); void (U::*_setter)(T);
Parameters _parameters;
}; };
template<class U, typename T> template<class U, typename T>
@@ -123,11 +175,17 @@ SetterAttr<U, T> attr(const QString &qualified_name, U &u, void (U::*setter)(T))
return SetterAttr<U, T>(qualified_name, u, setter); return SetterAttr<U, T>(qualified_name, u, setter);
} }
template<class U, typename T>
SetterAttr<U, T> attr(const QString &qualified_name, U &u, void (U::*setter)(T), const Parameters &parameters)
{
return SetterAttr<U, T>(qualified_name, u, setter, parameters);
}
template<class U, typename T, typename V> template<class U, typename T, typename V>
class GetterSetterAttr { class GetterSetterAttr {
public: public:
explicit GetterSetterAttr(const QString &qualified_name, U &u, T (U::*getter)() const, void (U::*setter)(V)) GetterSetterAttr(const QString &qualified_name, U &u, T (U::*getter)() const, void (U::*setter)(V))
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_getter(getter), _getter(getter),
@@ -135,6 +193,15 @@ public:
{ {
} }
GetterSetterAttr(const QString &qualified_name, U &u, T (U::*getter)() const, void (U::*setter)(V), const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_getter(getter),
_setter(setter),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
U &getObject() const { return _u; } U &getObject() const { return _u; }
@@ -143,11 +210,14 @@ public:
void (U::*getSetter() const)(V) { return _setter; } void (U::*getSetter() const)(V) { return _setter; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
U &_u; U &_u;
T (U::*_getter)() const; T (U::*_getter)() const;
void (U::*_setter)(V); void (U::*_setter)(V);
Parameters _parameters;
}; };
template<class U, typename T, typename V> template<class U, typename T, typename V>
@@ -156,27 +226,44 @@ GetterSetterAttr<U, T, V> attr(const QString &qualified_name, U &u, T (U::*gette
return GetterSetterAttr<U, T, V>(qualified_name, u, getter, setter); return GetterSetterAttr<U, T, V>(qualified_name, u, getter, setter);
} }
template<class U, typename T, typename V>
GetterSetterAttr<U, T, V> attr(const QString &qualified_name, U &u, T (U::*getter)() const, void (U::*setter)(V), const Parameters &parameters)
{
return GetterSetterAttr<U, T, V>(qualified_name, u, getter, setter, parameters);
}
template<class U, typename T> template<class U, typename T>
class GetFuncAttr { class GetFuncAttr {
public: public:
explicit GetFuncAttr(const QString &qualified_name, U &u, T (*get_func)(const U &)) GetFuncAttr(const QString &qualified_name, U &u, T (*get_func)(const U &))
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_get_func(get_func) _get_func(get_func)
{ {
} }
GetFuncAttr(const QString &qualified_name, U &u, T (*get_func)(const U &), const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_get_func(get_func),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
U &getObject() const { return _u; } U &getObject() const { return _u; }
T (*getGetFunc() const)(const U &) { return _get_func; } T (*getGetFunc() const)(const U &) { return _get_func; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
U &_u; U &_u;
T (*_get_func)(const U &); T (*_get_func)(const U &);
Parameters _parameters;
}; };
template<class U, typename T> template<class U, typename T>
@@ -185,27 +272,44 @@ GetFuncAttr<U, T> attr(const QString &qualified_name, const U &u, T (*get_func)(
return GetFuncAttr<U, T>(qualified_name, u, get_func); return GetFuncAttr<U, T>(qualified_name, u, get_func);
} }
template<class U, typename T>
GetFuncAttr<U, T> attr(const QString &qualified_name, const U &u, T (*get_func)(const U &), const Parameters &parameters)
{
return GetFuncAttr<U, T>(qualified_name, u, get_func, parameters);
}
template<class U, typename T> template<class U, typename T>
class SetFuncAttr { class SetFuncAttr {
public: public:
explicit SetFuncAttr(const QString &qualified_name, U &u, void (*set_func)(U &, T)) SetFuncAttr(const QString &qualified_name, U &u, void (*set_func)(U &, T))
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_set_func(set_func) _set_func(set_func)
{ {
} }
SetFuncAttr(const QString &qualified_name, U &u, void (*set_func)(U &, T), const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_set_func(set_func),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
U &getObject() const { return _u; } U &getObject() const { return _u; }
void (*getSetFunc() const)(U &, T) { return _set_func; } void (*getSetFunc() const)(U &, T) { return _set_func; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
U &_u; U &_u;
void (*_set_func)(U &, T); void (*_set_func)(U &, T);
Parameters _parameters;
}; };
template<class U, typename T> template<class U, typename T>
@@ -214,11 +318,17 @@ SetFuncAttr<U, T> attr(const QString &qualified_name, U &u, void (*set_func)(U &
return SetFuncAttr<U, T>(qualified_name, u, set_func); return SetFuncAttr<U, T>(qualified_name, u, set_func);
} }
template<class U, typename T>
SetFuncAttr<U, T> attr(const QString &qualified_name, U &u, void (*set_func)(U &, T), const Parameters &parameters)
{
return SetFuncAttr<U, T>(qualified_name, u, set_func, parameters);
}
template<class U, typename T, typename V> template<class U, typename T, typename V>
class GetSetFuncAttr { class GetSetFuncAttr {
public: public:
explicit GetSetFuncAttr(const QString &qualified_name, U &u, T (*get_func)(const U &), void (*set_func)(U &, V)) GetSetFuncAttr(const QString &qualified_name, U &u, T (*get_func)(const U &), void (*set_func)(U &, V))
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_get_func(get_func), _get_func(get_func),
@@ -226,6 +336,15 @@ public:
{ {
} }
GetSetFuncAttr(const QString &qualified_name, U &u, T (*get_func)(const U &), void (*set_func)(U &, V), const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_get_func(get_func),
_set_func(set_func),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
U &getObject() const { return _u; } U &getObject() const { return _u; }
@@ -234,11 +353,14 @@ public:
void (*getSetFunc() const)(U &, V) { return _set_func; } void (*getSetFunc() const)(U &, V) { return _set_func; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
U &_u; U &_u;
T (*_get_func)(const U &); T (*_get_func)(const U &);
void (*_set_func)(U &, V); void (*_set_func)(U &, V);
Parameters _parameters;
}; };
template<class U, typename T, typename V> template<class U, typename T, typename V>
@@ -247,6 +369,12 @@ GetSetFuncAttr<U, T, V> attr(const QString &qualified_name, U &u, T (*get_func)(
return GetSetFuncAttr<U, T, V>(qualified_name, u, get_func, set_func); return GetSetFuncAttr<U, T, V>(qualified_name, u, get_func, set_func);
} }
template<class U, typename T, typename V>
GetSetFuncAttr<U, T, V> attr(const QString &qualified_name, U &u, T (*get_func)(const U &), void (*set_func)(U &, V), const Parameters &parameters)
{
return GetSetFuncAttr<U, T, V>(qualified_name, u, get_func, set_func, parameters);
}
} }
#endif // QARK_ATTRIBUTE_H #endif // QARK_ATTRIBUTE_H

View File

@@ -32,6 +32,7 @@
#define QARK_BASECLASS_H #define QARK_BASECLASS_H
#include "typeregistry.h" #include "typeregistry.h"
#include "parameters.h"
#include <QString> #include <QString>
@@ -41,21 +42,31 @@ namespace qark {
template<class BASE, class DERIVED> template<class BASE, class DERIVED>
class Base { class Base {
public: public:
explicit Base(const QString &qualified_name, DERIVED &obj) Base(const QString &qualified_name, DERIVED &obj)
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_base(obj) _base(obj)
{ {
} }
Base(const QString &qualified_name, DERIVED &obj, const Parameters &parameters)
: _qualified_name(qualified_name),
_base(obj),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
const BASE &getBase() const { return _base; } const BASE &getBase() const { return _base; }
BASE &getBase() { return _base; } BASE &getBase() { return _base; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
BASE &_base; BASE &_base;
Parameters _parameters;
}; };
template<class BASE, class DERIVED> template<class BASE, class DERIVED>
@@ -64,18 +75,36 @@ Base<BASE, DERIVED> base(const QString &qualified_name, DERIVED &obj)
return Base<BASE, DERIVED>(qualified_name, obj); return Base<BASE, DERIVED>(qualified_name, obj);
} }
template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(const QString &qualified_name, DERIVED &obj, const Parameters &parameters)
{
return Base<BASE, DERIVED>(qualified_name, obj, parameters);
}
template<class BASE, class DERIVED> template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(const QString &qualified_name, DERIVED *&obj) Base<BASE, DERIVED> base(const QString &qualified_name, DERIVED *&obj)
{ {
return Base<BASE, DERIVED>(qualified_name, *obj); return Base<BASE, DERIVED>(qualified_name, *obj);
} }
template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(const QString &qualified_name, DERIVED *&obj, const Parameters &parameters)
{
return Base<BASE, DERIVED>(qualified_name, *obj, parameters);
}
template<class BASE, class DERIVED> template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(DERIVED &obj) Base<BASE, DERIVED> base(DERIVED &obj)
{ {
return Base<BASE, DERIVED>(QString(QStringLiteral("base-%1")).arg(get_type_uid<BASE>()), obj); return Base<BASE, DERIVED>(QString(QStringLiteral("base-%1")).arg(get_type_uid<BASE>()), obj);
} }
template<class BASE, class DERIVED>
Base<BASE, DERIVED> base(DERIVED &obj, const Parameters &parameters)
{
return Base<BASE, DERIVED>(QString(QStringLiteral("base-%1")).arg(get_type_uid<BASE>()), obj, parameters);
}
} }
#endif // QARK_BASECLASS_H #endif // QARK_BASECLASS_H

View File

@@ -28,8 +28,8 @@
** **
****************************************************************************/ ****************************************************************************/
#ifndef QMT_FRIEND_ACCESS_H #ifndef QARK_FRIEND_ACCESS_H
#define QMT_FRIEND_ACCESS_H #define QARK_FRIEND_ACCESS_H
#define QARK_FRIEND_ACCESS \ #define QARK_FRIEND_ACCESS \
template<class Archive, class T> \ template<class Archive, class T> \

View File

@@ -28,59 +28,44 @@
** **
****************************************************************************/ ****************************************************************************/
#ifndef QMT_DIAGRAMREFERENCESERIALIZER_H #ifndef QARK_PARAMETER_H
#define QMT_DIAGRAMREFERENCESERIALIZER_H #define QARK_PARAMETER_H
#include "qmt/infrastructure/uid.h" #include "flag.h"
#include <QString> namespace qark {
QT_BEGIN_NAMESPACE class Parameters
class QXmlStreamReader;
class QXmlStreamWriter;
QT_END_NAMESPACE
namespace qmt {
class Project;
class MDiagram;
class QMT_EXPORT DiagramReferenceSerializer
{ {
public:
struct Reference {
Reference();
Reference(const Uid &model_uid, const Uid &diagram_uid);
Uid _model_uid;
Uid _diagram_uid;
};
public:
DiagramReferenceSerializer();
~DiagramReferenceSerializer();
public: public:
void save(const QString &file_name, const Reference &reference); Parameters()
: _flags(0)
{
}
QByteArray save(const Project *project, const MDiagram *diagram); Parameters(const Flag &flag)
: _flags(flag.getMask())
{
}
Reference load(const QString &file_name); public:
Reference load(const QByteArray &contents); void setFlag(const Flag &flag) { _flags |= flag.getMask(); }
void clearFlag(const Flag &flag) { _flags &= ~flag.getMask(); }
bool hasFlag(const Flag &flag) const { return (_flags & flag.getMask()) != 0; }
bool takeFlag(const Flag &flag) { bool f = (_flags & flag.getMask()) != 0; _flags &= ~flag.getMask(); return f; }
private: private:
void write(const Reference &reference, QXmlStreamWriter *writer); Flag::mask_type _flags;
Reference read(QXmlStreamReader *stream_reader);
}; };
} }
#endif // QMT_DIAGRAMREFERENCESERIALIZER_H #endif // QARK_PARAMETER_H

View File

@@ -75,7 +75,7 @@ private:
typedef QList<Node *> children_type; typedef QList<Node *> children_type;
public: public:
virtual ~Node() { } virtual ~Node() { qDeleteAll(_children); }
const children_type &getChildren() const { return _children; } const children_type &getChildren() const { return _children; }
@@ -83,8 +83,6 @@ private:
virtual void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); } virtual void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); }
virtual void acceptForwardRef(QXmlInArchive &visitor, const impl::ObjectId &id) { visitor.visitForwardRef(this, id); }
void append(Node *node) { _children.push_back(node); } void append(Node *node) { _children.push_back(node); }
private: private:
@@ -237,8 +235,6 @@ private:
void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); } void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); }
void acceptForwardRef(QXmlInArchive &visitor, const impl::ObjectId &id) { visitor.visitForwardRef(this, id); }
Ref<T> &getReference() { return _ref; } Ref<T> &getReference() { return _ref; }
private: private:
@@ -256,8 +252,6 @@ private:
void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); } void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); }
void acceptForwardRef(QXmlInArchive &visitor, const impl::ObjectId &id) { visitor.visitForwardRef(this, id); }
SetterRef<U, T> &getReference() { return _ref; } SetterRef<U, T> &getReference() { return _ref; }
private: private:
@@ -275,8 +269,6 @@ private:
void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); } void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); }
void acceptForwardRef(QXmlInArchive &visitor, const impl::ObjectId &id) { visitor.visitForwardRef(this, id); }
GetterSetterRef<U, T, V> &getReference() { return _ref; } GetterSetterRef<U, T, V> &getReference() { return _ref; }
private: private:
@@ -294,8 +286,6 @@ private:
void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); } void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); }
void acceptForwardRef(QXmlInArchive &visitor, const impl::ObjectId &id) { visitor.visitForwardRef(this, id); }
SetFuncRef<U, T> &getReference() { return _ref; } SetFuncRef<U, T> &getReference() { return _ref; }
private: private:
@@ -313,35 +303,23 @@ private:
void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); } void accept(QXmlInArchive &visitor, const XmlTag &tag) { visitor.visit(this, tag); }
void acceptForwardRef(QXmlInArchive &visitor, const impl::ObjectId &id) { visitor.visitForwardRef(this, id); }
GetSetFuncRef<U, T, V> &getReference() { return _ref; } GetSetFuncRef<U, T, V> &getReference() { return _ref; }
private: private:
GetSetFuncRef<U, T, V> _ref; GetSetFuncRef<U, T, V> _ref;
}; };
struct ForwardReference {
ForwardReference(Node *node, const impl::ObjectId &id) : _node(node), _id(id) { }
Node *_node;
impl::ObjectId _id;
};
public: public:
explicit QXmlInArchive(QXmlStreamReader &stream) explicit QXmlInArchive(QXmlStreamReader &stream)
: _stream(stream), : _stream(stream),
_end_tag_was_read(false), _end_tag_was_read(false),
_root_node(0),
_current_ref_node(0) _current_ref_node(0)
{ {
} }
~QXmlInArchive() ~QXmlInArchive()
{ {
foreach(const ForwardReference &forward_ref, _forward_references) {
forward_ref._node->acceptForwardRef(*this, forward_ref._id);
}
} }
public: public:
@@ -387,9 +365,7 @@ public:
void append(const Tag &tag) void append(const Tag &tag)
{ {
TagNode *node = new TagNode(tag); TagNode *node = new TagNode(tag);
if (_node_stack.empty()) { if (!_node_stack.empty()) {
_root_node = node;
} else {
_node_stack.top()->append(node); _node_stack.top()->append(node);
} }
_node_stack.push(node); _node_stack.push(node);
@@ -399,9 +375,7 @@ public:
void append(const Object<T> &object) void append(const Object<T> &object)
{ {
ObjectNode<T> *node = new ObjectNode<T>(object); ObjectNode<T> *node = new ObjectNode<T>(object);
if (_node_stack.empty()) { if (!_node_stack.empty()) {
_root_node = node;
} else {
_node_stack.top()->append(node); _node_stack.top()->append(node);
} }
_node_stack.push(node); _node_stack.push(node);
@@ -409,13 +383,14 @@ public:
void append(const End &) void append(const End &)
{ {
_node_stack.pop(); Node *node = _node_stack.pop();
if (_node_stack.empty()) { if (_node_stack.empty()) {
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (xml_tag._tag_name != _root_node->getQualifiedName() || xml_tag._end_tag) { if (xml_tag._tag_name != node->getQualifiedName() || xml_tag._end_tag) {
throw FileFormatException(); throw FileFormatException();
} }
_root_node->accept(*this, xml_tag); node->accept(*this, xml_tag);
delete node;
} }
} }
@@ -587,13 +562,8 @@ public:
if (_loading_ref_map.hasObject(id)) { if (_loading_ref_map.hasObject(id)) {
p = _loading_ref_map.getObject<T *>(id); p = _loading_ref_map.getObject<T *>(id);
} else { } else {
if (_current_ref_node == 0) {
throw UnexpectedForwardReference(); throw UnexpectedForwardReference();
} }
_forward_references.append(ForwardReference(_current_ref_node, id));
// node is eaten, also used as flag for forward references
_current_ref_node = 0;
}
} }
private: private:
@@ -634,11 +604,6 @@ private:
throw FileFormatException(); throw FileFormatException();
} }
void visitForwardRef(Node *, const impl::ObjectId &)
{
throw UnexpectedForwardReference();
}
void visit(TagNode *node, const XmlTag &) void visit(TagNode *node, const XmlTag &)
{ {
readChildren(node); readChildren(node);
@@ -656,7 +621,7 @@ private:
template<class T, class U> template<class T, class U>
void visit(BaseNode<T, U> *node, const XmlTag &) void visit(BaseNode<T, U> *node, const XmlTag &)
{ {
(*this) >> node->getBase().getBase(); load(*this, node->getBase().getBase(), node->getBase().getParameters());
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getBase().getQualifiedName()) { if (!xml_tag._end_tag || xml_tag._tag_name != node->getBase().getQualifiedName()) {
throw FileFormatException(); throw FileFormatException();
@@ -666,7 +631,7 @@ private:
template<class T> template<class T>
void visit(AttrNode<T> *node, const XmlTag &) void visit(AttrNode<T> *node, const XmlTag &)
{ {
(*this) >> *node->getAttribute().getValue(); load(*this, *node->getAttribute().getValue(), node->getAttribute().getParameters());
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) { if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
throw FileFormatException(); throw FileFormatException();
@@ -677,7 +642,7 @@ private:
void visit(SetterAttrNode<U, T> *node, const XmlTag &) void visit(SetterAttrNode<U, T> *node, const XmlTag &)
{ {
T value; T value;
(*this) >> value; load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value); (node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value);
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) { if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
@@ -689,7 +654,7 @@ private:
void visit(SetterAttrNode<U, const T &> *node, const XmlTag &) void visit(SetterAttrNode<U, const T &> *node, const XmlTag &)
{ {
T value; T value;
(*this) >> value; load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value); (node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value);
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) { if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
@@ -701,7 +666,7 @@ private:
void visit(GetterSetterAttrNode<U, T, V> *node, const XmlTag &) void visit(GetterSetterAttrNode<U, T, V> *node, const XmlTag &)
{ {
V value; V value;
(*this) >> value; load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value); (node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value);
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) { if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
@@ -713,7 +678,7 @@ private:
void visit(GetterSetterAttrNode<U, T, const V &> *node, const XmlTag &) void visit(GetterSetterAttrNode<U, T, const V &> *node, const XmlTag &)
{ {
V value; V value;
(*this) >> value; load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value); (node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value);
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) { if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
@@ -725,7 +690,7 @@ private:
void visit(SetFuncAttrNode<U, T> *node, const XmlTag &) void visit(SetFuncAttrNode<U, T> *node, const XmlTag &)
{ {
T value; T value;
(*this) >> value; load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value); (node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value);
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) { if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
@@ -737,7 +702,7 @@ private:
void visit(SetFuncAttrNode<U, const T &> *node, const XmlTag &) void visit(SetFuncAttrNode<U, const T &> *node, const XmlTag &)
{ {
T value; T value;
(*this) >> value; load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value); (node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value);
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) { if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
@@ -749,7 +714,7 @@ private:
void visit(GetSetFuncAttrNode<U, T, V> *node, const XmlTag &) void visit(GetSetFuncAttrNode<U, T, V> *node, const XmlTag &)
{ {
V value; V value;
(*this) >> value; load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value); (node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value);
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) { if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
@@ -761,7 +726,7 @@ private:
void visit(GetSetFuncAttrNode<U, T, const V &> *node, const XmlTag &) void visit(GetSetFuncAttrNode<U, T, const V &> *node, const XmlTag &)
{ {
V value; V value;
(*this) >> value; load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value); (node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value);
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) { if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
@@ -774,8 +739,8 @@ private:
{ {
_current_ref_node = node; _current_ref_node = node;
T value = T(); T value = T();
(*this) >> value; load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not eaten by forward reference if (_current_ref_node != 0) { // ref node was not consumed by forward reference
*node->getReference().getValue() = value; *node->getReference().getValue() = value;
_current_ref_node = 0; _current_ref_node = 0;
} }
@@ -785,23 +750,13 @@ private:
} }
} }
template<typename T>
void visitForwardRef(RefNode<T> *node, const impl::ObjectId &id)
{
if (!_loading_ref_map.hasObject(id)) {
throw UnexpectedForwardReference();
}
T value = _loading_ref_map.getObject<T>(id);
*(node->getReference().getValue()) = value;
}
template<class U, typename T> template<class U, typename T>
void visit(SetterRefNode<U, T> *node, const XmlTag &) void visit(SetterRefNode<U, T> *node, const XmlTag &)
{ {
_current_ref_node = node; _current_ref_node = node;
T value; T value;
(*this) >> value; load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not eaten by forward reference if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value); (node->getReference().getObject().*(node->getReference().getSetter()))(value);
_current_ref_node = 0; _current_ref_node = 0;
} }
@@ -816,8 +771,8 @@ private:
{ {
_current_ref_node = node; _current_ref_node = node;
T value; T value;
(*this) >> value; load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not eaten by forward reference if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value); (node->getReference().getObject().*(node->getReference().getSetter()))(value);
_current_ref_node = 0; _current_ref_node = 0;
} }
@@ -827,33 +782,13 @@ private:
} }
} }
template<class U, typename T>
void visitForwardRef(SetterRefNode<U, T> *node, const impl::ObjectId &id)
{
if (!_loading_ref_map.hasObject(id)) {
throw UnexpectedForwardReference();
}
T value = _loading_ref_map.getObject<T>(id);
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
}
template<class U, typename T>
void visitForwardRef(SetterRefNode<U, T const &> *node, const impl::ObjectId &id)
{
if (!_loading_ref_map.hasObject(id)) {
throw UnexpectedForwardReference();
}
T value = _loading_ref_map.getObject<T>(id);
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
}
template<class U, typename T, typename V> template<class U, typename T, typename V>
void visit(GetterSetterRefNode<U, T, V> *node, const XmlTag &) void visit(GetterSetterRefNode<U, T, V> *node, const XmlTag &)
{ {
_current_ref_node = node; _current_ref_node = node;
V value; V value;
(*this) >> value; load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not eaten by forward reference if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value); (node->getReference().getObject().*(node->getReference().getSetter()))(value);
_current_ref_node = 0; _current_ref_node = 0;
} }
@@ -868,8 +803,8 @@ private:
{ {
_current_ref_node = node; _current_ref_node = node;
V value; V value;
(*this) >> value; load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not eaten by forward reference if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value); (node->getReference().getObject().*(node->getReference().getSetter()))(value);
_current_ref_node = 0; _current_ref_node = 0;
} }
@@ -879,34 +814,14 @@ private:
} }
} }
template<class U, typename T, typename V>
void visitForwardRef(GetterSetterRefNode<U, T, V> *node, const impl::ObjectId &id)
{
if (!_loading_ref_map.hasObject(id)) {
throw UnexpectedForwardReference();
}
V value = _loading_ref_map.getObject<V>(id);
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
}
template<class U, typename T, typename V>
void visitForwardRef(GetterSetterRefNode<U, T, V const &> *node, const impl::ObjectId &id)
{
if (!_loading_ref_map.hasObject(id)) {
throw UnexpectedForwardReference();
}
V value = _loading_ref_map.getObject<V>(id);
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
}
template<class U, typename T> template<class U, typename T>
void visit(SetFuncRefNode<U, T> *node, const XmlTag &) void visit(SetFuncRefNode<U, T> *node, const XmlTag &)
{ {
_current_ref_node = node; _current_ref_node = node;
T value; T value;
(*this) >> value; load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not eaten by forward reference if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value); (node->getReference().getSetFunc())(node->getReference().getObject(), value);
_current_ref_node = 0; _current_ref_node = 0;
} }
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
@@ -920,9 +835,9 @@ private:
{ {
_current_ref_node = node; _current_ref_node = node;
T value; T value;
(*this) >> value; load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not eaten by forward reference if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value); (node->getReference().getSetFunc())(node->getReference().getObject(), value);
_current_ref_node = 0; _current_ref_node = 0;
} }
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
@@ -931,34 +846,14 @@ private:
} }
} }
template<class U, typename T>
void visitForwardRef(SetFuncRefNode<U, T> *node, const impl::ObjectId &id)
{
if (!_loading_ref_map.hasObject(id)) {
throw UnexpectedForwardReference();
}
T value = _loading_ref_map.getObject<T>(id);
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
}
template<class U, typename T>
void visitForwardRef(SetFuncRefNode<U, T const &> *node, const impl::ObjectId &id)
{
if (!_loading_ref_map.hasObject(id)) {
throw UnexpectedForwardReference();
}
T value = _loading_ref_map.getObject<T>(id);
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
}
template<class U, typename T, typename V> template<class U, typename T, typename V>
void visit(GetSetFuncRefNode<U, T, V> *node, const XmlTag &) void visit(GetSetFuncRefNode<U, T, V> *node, const XmlTag &)
{ {
_current_ref_node = node; _current_ref_node = node;
V value; V value;
(*this) >> value; load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not eaten by forward reference if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value); (node->getReference().getSetFunc())(node->getReference().getObject(), value);
_current_ref_node = 0; _current_ref_node = 0;
} }
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
@@ -972,9 +867,9 @@ private:
{ {
_current_ref_node = node; _current_ref_node = node;
V value; V value;
(*this) >> value; load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not eaten by forward reference if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value); (node->getReference().getSetFunc())(node->getReference().getObject(), value);
_current_ref_node = 0; _current_ref_node = 0;
} }
XmlTag xml_tag = readTag(); XmlTag xml_tag = readTag();
@@ -983,26 +878,6 @@ private:
} }
} }
template<class U, typename T, typename V>
void visitForwardRef(GetSetFuncRefNode<U, T, V> *node, const impl::ObjectId &id)
{
if (!_loading_ref_map.hasObject(id)) {
throw UnexpectedForwardReference();
}
V value = _loading_ref_map.getObject<V>(id);
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
}
template<class U, typename T, typename V>
void visitForwardRef(GetSetFuncRefNode<U, T, V const &> *node, const impl::ObjectId &id)
{
if (!_loading_ref_map.hasObject(id)) {
throw UnexpectedForwardReference();
}
V value = _loading_ref_map.getObject<V>(id);
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
}
private: private:
inline XmlTag readTag(); inline XmlTag readTag();
@@ -1012,11 +887,9 @@ private:
private: private:
QXmlStreamReader &_stream; QXmlStreamReader &_stream;
bool _end_tag_was_read; bool _end_tag_was_read;
Node *_root_node;
QStack<Node *> _node_stack; QStack<Node *> _node_stack;
impl::LoadingRefMap _loading_ref_map; impl::LoadingRefMap _loading_ref_map;
Node *_current_ref_node; Node *_current_ref_node;
QList<ForwardReference> _forward_references;
}; };

View File

@@ -49,6 +49,11 @@ class QXmlOutArchive :
{ {
public: public:
class UnsupportedForwardReference :
public std::exception
{
};
class DanglingReferences : class DanglingReferences :
public std::exception public std::exception
{ {
@@ -58,6 +63,7 @@ public:
static const bool out_archive = true; static const bool out_archive = true;
public: public:
QXmlOutArchive(QXmlStreamWriter &stream) QXmlOutArchive(QXmlStreamWriter &stream)
: _stream(stream), : _stream(stream),
_next_pointer_is_reference(false) _next_pointer_is_reference(false)
@@ -76,6 +82,9 @@ public:
template<typename T> template<typename T>
void write(T *p) void write(T *p)
{ {
if (!_saving_ref_map.hasDefinedRef(p)) {
throw UnsupportedForwardReference();
}
write(_saving_ref_map.getRef(p).get()); write(_saving_ref_map.getRef(p).get());
} }
@@ -132,7 +141,12 @@ public:
void beginElement(const Object<T> &object) void beginElement(const Object<T> &object)
{ {
_stream.writeStartElement(object.getQualifiedName()); _stream.writeStartElement(object.getQualifiedName());
_stream.writeAttribute(QLatin1String("id"), QString::number(_saving_ref_map.getRef(object.getObject(), true).get())); // TODO implement key attribute
// Currently qmodel files do not use references at all
// so writing reference keys are not needed. If this
// changes keys should be implemented as a generic
// concept getting key from object (e.g. with a function
// registered per type in typeregistry)
} }
void endElement(const End &) void endElement(const End &)

View File

@@ -31,6 +31,8 @@
#ifndef QARK_REFERENCE_H #ifndef QARK_REFERENCE_H
#define QARK_REFERENCE_H #define QARK_REFERENCE_H
#include "parameters.h"
#include <QString> #include <QString>
namespace qark { namespace qark {
@@ -38,19 +40,29 @@ namespace qark {
template<typename T> template<typename T>
class Ref { class Ref {
public: public:
explicit Ref(const QString &qualified_name, T *value) Ref(const QString &qualified_name, T *value)
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_value(value) _value(value)
{ {
} }
Ref(const QString &qualified_name, T *value, const Parameters &parameters)
: _qualified_name(qualified_name),
_value(value),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
T *getValue() const { return _value; } T *getValue() const { return _value; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
T *_value; T *_value;
Parameters _parameters;
}; };
template<typename T> template<typename T>
@@ -59,32 +71,56 @@ Ref<T * const> ref(const QString &qualified_name, T * const &value)
return Ref<T * const>(qualified_name, &value); return Ref<T * const>(qualified_name, &value);
} }
template<typename T>
Ref<T * const> ref(const QString &qualified_name, T * const &value, const Parameters &parameters)
{
return Ref<T * const>(qualified_name, &value, parameters);
}
template<typename T> template<typename T>
Ref<T *> ref(const QString &qualified_name, T *&value) Ref<T *> ref(const QString &qualified_name, T *&value)
{ {
return Ref<T *>(qualified_name, &value); return Ref<T *>(qualified_name, &value);
} }
template<typename T>
Ref<T *> ref(const QString &qualified_name, T *&value, const Parameters &parameters)
{
return Ref<T *>(qualified_name, &value, parameters);
}
template<class U, typename T> template<class U, typename T>
class GetterRef { class GetterRef {
public: public:
explicit GetterRef(const QString &qualified_name, const U &u, T (U::*getter)() const) GetterRef(const QString &qualified_name, const U &u, T (U::*getter)() const)
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_getter(getter) _getter(getter)
{ {
} }
GetterRef(const QString &qualified_name, const U &u, T (U::*getter)() const, const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_getter(getter),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
const U &getObject() const { return _u; } const U &getObject() const { return _u; }
T (U::*getGetter() const)() const { return _getter; } T (U::*getGetter() const)() const { return _getter; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
const U &_u; const U &_u;
T (U::*_getter)() const; T (U::*_getter)() const;
Parameters _parameters;
}; };
template<class U, typename T> template<class U, typename T>
@@ -93,27 +129,44 @@ GetterRef<U, T *> ref(const QString &qualified_name, const U &u, T *(U::*getter)
return GetterRef<U, T *>(qualified_name, u, getter); return GetterRef<U, T *>(qualified_name, u, getter);
} }
template<class U, typename T>
GetterRef<U, T *> ref(const QString &qualified_name, const U &u, T *(U::*getter)() const, const Parameters &parameters)
{
return GetterRef<U, T *>(qualified_name, u, getter, parameters);
}
template<class U, typename T> template<class U, typename T>
class SetterRef { class SetterRef {
public: public:
explicit SetterRef(const QString &qualified_name, U &u, void (U::*setter)(T)) SetterRef(const QString &qualified_name, U &u, void (U::*setter)(T))
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_setter(setter) _setter(setter)
{ {
} }
SetterRef(const QString &qualified_name, U &u, void (U::*setter)(T), const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_setter(setter),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
U &getObject() const { return _u; } U &getObject() const { return _u; }
void (U::*getSetter() const)(T) { return _setter; } void (U::*getSetter() const)(T) { return _setter; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
U &_u; U &_u;
void (U::*_setter)(T); void (U::*_setter)(T);
Parameters _parameters;
}; };
template<class U, class T> template<class U, class T>
@@ -122,16 +175,29 @@ SetterRef<U, T *> ref(const QString &qualified_name, U &u, void (U::*setter)(T *
return SetterRef<U, T *>(qualified_name, u, setter); return SetterRef<U, T *>(qualified_name, u, setter);
} }
template<class U, class T>
SetterRef<U, T *> ref(const QString &qualified_name, U &u, void (U::*setter)(T *), const Parameters &parameters)
{
return SetterRef<U, T *>(qualified_name, u, setter, parameters);
}
template<class U, class T> template<class U, class T>
SetterRef<U, T * const &> ref(const QString &qualified_name, U &u, void (U::*setter)(T * const &)) SetterRef<U, T * const &> ref(const QString &qualified_name, U &u, void (U::*setter)(T * const &))
{ {
return SetterRef<U, T * const &>(qualified_name, u, setter); return SetterRef<U, T * const &>(qualified_name, u, setter);
} }
template<class U, class T>
SetterRef<U, T * const &> ref(const QString &qualified_name, U &u, void (U::*setter)(T * const &), const Parameters &parameters)
{
return SetterRef<U, T * const &>(qualified_name, u, setter, parameters);
}
template<class U, typename T, typename V> template<class U, typename T, typename V>
class GetterSetterRef { class GetterSetterRef {
public: public:
explicit GetterSetterRef(const QString &qualified_name, U &u, T (U::*getter)() const, void (U::*setter)(V)) GetterSetterRef(const QString &qualified_name, U &u, T (U::*getter)() const, void (U::*setter)(V))
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_getter(getter), _getter(getter),
@@ -139,6 +205,15 @@ public:
{ {
} }
GetterSetterRef(const QString &qualified_name, U &u, T (U::*getter)() const, void (U::*setter)(V), const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_getter(getter),
_setter(setter),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
U &getObject() const { return _u; } U &getObject() const { return _u; }
@@ -147,11 +222,14 @@ public:
void (U::*getSetter() const)(V) { return _setter; } void (U::*getSetter() const)(V) { return _setter; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
U &_u; U &_u;
T (U::*_getter)() const; T (U::*_getter)() const;
void (U::*_setter)(V); void (U::*_setter)(V);
Parameters _parameters;
}; };
template<class U, typename T, typename V> template<class U, typename T, typename V>
@@ -160,32 +238,56 @@ GetterSetterRef<U, T *, V *> ref(const QString &qualified_name, U &u, T *(U::*ge
return GetterSetterRef<U, T *, V *>(qualified_name, u, getter, setter); return GetterSetterRef<U, T *, V *>(qualified_name, u, getter, setter);
} }
template<class U, typename T, typename V>
GetterSetterRef<U, T *, V *> ref(const QString &qualified_name, U &u, T *(U::*getter)() const, void (U::*setter)(V *), const Parameters &parameters)
{
return GetterSetterRef<U, T *, V *>(qualified_name, u, getter, setter, parameters);
}
template<class U, typename T, typename V> template<class U, typename T, typename V>
GetterSetterRef<U, T *, V * const &> ref(const QString &qualified_name, U &u, T *(U::*getter)() const, void (U::*setter)(V * const &)) GetterSetterRef<U, T *, V * const &> ref(const QString &qualified_name, U &u, T *(U::*getter)() const, void (U::*setter)(V * const &))
{ {
return GetterSetterRef<U, T *, V * const &>(qualified_name, u, getter, setter); return GetterSetterRef<U, T *, V * const &>(qualified_name, u, getter, setter);
} }
template<class U, typename T, typename V>
GetterSetterRef<U, T *, V * const &> ref(const QString &qualified_name, U &u, T *(U::*getter)() const, void (U::*setter)(V * const &), const Parameters &parameters)
{
return GetterSetterRef<U, T *, V * const &>(qualified_name, u, getter, setter, parameters);
}
template<class U, typename T> template<class U, typename T>
class GetFuncRef { class GetFuncRef {
public: public:
explicit GetFuncRef(const QString &qualified_name, const U &u, T (*get_func)(const U &)) GetFuncRef(const QString &qualified_name, const U &u, T (*get_func)(const U &))
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_get_func(get_func) _get_func(get_func)
{ {
} }
GetFuncRef(const QString &qualified_name, const U &u, T (*get_func)(const U &), const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_get_func(get_func),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
const U &getObject() const { return _u; } const U &getObject() const { return _u; }
T (*getGetFunc() const)(const U &) { return _get_func; } T (*getGetFunc() const)(const U &) { return _get_func; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
const U &_u; const U &_u;
T (*_get_func)(const U &); T (*_get_func)(const U &);
Parameters _parameters;
}; };
template<class U, typename T> template<class U, typename T>
@@ -194,27 +296,44 @@ GetFuncRef<U, T *> ref(const QString &qualified_name, const U &u, T *(*get_func)
return GetFuncRef<U, T *>(qualified_name, u, get_func); return GetFuncRef<U, T *>(qualified_name, u, get_func);
} }
template<class U, typename T>
GetFuncRef<U, T *> ref(const QString &qualified_name, const U &u, T *(*get_func)(const U &), const Parameters &parameters)
{
return GetFuncRef<U, T *>(qualified_name, u, get_func, parameters);
}
template<class U, typename T> template<class U, typename T>
class SetFuncRef { class SetFuncRef {
public: public:
explicit SetFuncRef(const QString &qualified_name, U &u, void (*set_func)(U &, T)) SetFuncRef(const QString &qualified_name, U &u, void (*set_func)(U &, T))
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_set_func(set_func) _set_func(set_func)
{ {
} }
SetFuncRef(const QString &qualified_name, U &u, void (*set_func)(U &, T), const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_set_func(set_func),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
U &getObject() const { return _u; } U &getObject() const { return _u; }
void (*getSetFunc() const)(U &, T) { return _set_func; } void (*getSetFunc() const)(U &, T) { return _set_func; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
U &_u; U &_u;
void (*_set_func)(U &, T); void (*_set_func)(U &, T);
Parameters _parameters;
}; };
template<class U, class T> template<class U, class T>
@@ -223,16 +342,29 @@ SetFuncRef<U, T *> ref(const QString &qualified_name, U &u, void (*set_func)(U &
return SetFuncRef<U, T *>(qualified_name, u, set_func); return SetFuncRef<U, T *>(qualified_name, u, set_func);
} }
template<class U, class T>
SetFuncRef<U, T *> ref(const QString &qualified_name, U &u, void (*set_func)(U &, T *), const Parameters &parameters)
{
return SetFuncRef<U, T *>(qualified_name, u, set_func, parameters);
}
template<class U, class T> template<class U, class T>
SetFuncRef<U, T * const &> ref(const QString &qualified_name, U &u, void (*set_func)(U &, T * const &)) SetFuncRef<U, T * const &> ref(const QString &qualified_name, U &u, void (*set_func)(U &, T * const &))
{ {
return SetFuncRef<U, T * const &>(qualified_name, u, set_func); return SetFuncRef<U, T * const &>(qualified_name, u, set_func);
} }
template<class U, class T>
SetFuncRef<U, T * const &> ref(const QString &qualified_name, U &u, void (*set_func)(U &, T * const &), const Parameters &parameters)
{
return SetFuncRef<U, T * const &>(qualified_name, u, set_func, parameters);
}
template<class U, typename T, typename V> template<class U, typename T, typename V>
class GetSetFuncRef { class GetSetFuncRef {
public: public:
explicit GetSetFuncRef(const QString &qualified_name, U &u, T (*get_func)(const U &), void (*set_func)(U &, V)) GetSetFuncRef(const QString &qualified_name, U &u, T (*get_func)(const U &), void (*set_func)(U &, V))
: _qualified_name(qualified_name), : _qualified_name(qualified_name),
_u(u), _u(u),
_get_func(get_func), _get_func(get_func),
@@ -240,6 +372,15 @@ public:
{ {
} }
GetSetFuncRef(const QString &qualified_name, U &u, T (*get_func)(const U &), void (*set_func)(U &, V), const Parameters &parameters)
: _qualified_name(qualified_name),
_u(u),
_get_func(get_func),
_set_func(set_func),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
U &getObject() const { return _u; } U &getObject() const { return _u; }
@@ -248,11 +389,14 @@ public:
void (*getSetFunc() const)(U &, V) { return _set_func; } void (*getSetFunc() const)(U &, V) { return _set_func; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
U &_u; U &_u;
T (*_get_func)(const U &); T (*_get_func)(const U &);
void (*_set_func)(U &, V); void (*_set_func)(U &, V);
Parameters _parameters;
}; };
template<class U, typename T, typename V> template<class U, typename T, typename V>
@@ -261,12 +405,24 @@ GetSetFuncRef<U, T *, V *> ref(const QString &qualified_name, U &u, T *(*get_fun
return GetSetFuncRef<U, T *, V *>(qualified_name, u, get_func, set_func); return GetSetFuncRef<U, T *, V *>(qualified_name, u, get_func, set_func);
} }
template<class U, typename T, typename V>
GetSetFuncRef<U, T *, V *> ref(const QString &qualified_name, U &u, T *(*get_func)(const U &), void (*set_func)(U &, V *), const Parameters &parameters)
{
return GetSetFuncRef<U, T *, V *>(qualified_name, u, get_func, set_func, parameters);
}
template<class U, typename T, typename V> template<class U, typename T, typename V>
GetSetFuncRef<U, T *, V * const &> ref(const QString &qualified_name, U &u, T *(*get_func)(const U &), void (*set_func)(U &, V * const &)) GetSetFuncRef<U, T *, V * const &> ref(const QString &qualified_name, U &u, T *(*get_func)(const U &), void (*set_func)(U &, V * const &))
{ {
return GetSetFuncRef<U, T *, V * const &>(qualified_name, u, get_func, set_func); return GetSetFuncRef<U, T *, V * const &>(qualified_name, u, get_func, set_func);
} }
template<class U, typename T, typename V>
GetSetFuncRef<U, T *, V * const &> ref(const QString &qualified_name, U &u, T *(*get_func)(const U &), void (*set_func)(U &, V * const &), const Parameters &parameters)
{
return GetSetFuncRef<U, T *, V * const &>(qualified_name, u, get_func, set_func, parameters);
}
} }
#endif // QARK_REFERENCE_H #endif // QARK_REFERENCE_H

View File

@@ -38,6 +38,7 @@
#include "access.h" #include "access.h"
#include "typeregistry.h" #include "typeregistry.h"
#include "serialize_pointer.h"
#include "serialize_basic.h" #include "serialize_basic.h"
#include "serialize_container.h" #include "serialize_container.h"
#include "serialize_enum.h" #include "serialize_enum.h"
@@ -51,102 +52,27 @@ namespace qark {
template<class Archive, class T> template<class Archive, class T>
inline Archive &operator<<(Archive &archive, const T &t) inline Archive &operator<<(Archive &archive, const T &t)
{ {
save(archive, t); save(archive, t, Parameters());
return archive; return archive;
} }
template<class Archive, class T> template<class Archive, class T>
inline Archive &operator>>(Archive &archive, T &t) inline Archive &operator>>(Archive &archive, T &t)
{ {
load(archive, t); load(archive, t, Parameters());
return archive; return archive;
} }
template<class Archive, class T> template<class Archive, class T>
typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, T &t) typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, T &t)
{ {
save(archive, (const T &) t); return archive << t;
return archive;
} }
template<class Archive, class T> template<class Archive, class T>
typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive &archive, T &t) typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive &archive, T &t)
{ {
load(archive, t); return archive >> t;
return archive;
}
template<class Archive, class T>
inline Archive &operator<<(Archive &archive, T *p)
{
if (p) {
if (archive.isReference(p)) {
archive.beginPointer();
archive.write(p);
archive.endPointer();
} else {
if (typeid(*p) == typeid(T)) {
archive.beginInstance();
registry::save_pointer<Archive, T, T>(archive, p);
archive.endInstance();
} else {
archive.beginInstance(get_type_uid(*p));
//typename registry::TypeRegistry<Archive, typename qark::non_const<T>::type>::type_info type_data
// = get_type_info<Archive, typename qark::non_const<T>::type>(*p);
typename registry::TypeRegistry<Archive, T>::type_info type_data = get_type_info<Archive, T>(*p);
if (type_data.save_func == 0) {
throw unregistered_type();
} else {
type_data.save_func(archive, p);
}
archive.endInstance();
}
}
} else {
archive.beginNullPointer();
archive.endNullPointer();
}
return archive;
}
template<class Archive, class T>
inline Archive &operator>>(Archive &archive, T *&p)
{
typename Archive::ReferenceTag ref_tag = archive.readReferenceTag();
switch (ref_tag.kind) {
case Archive::NULLPOINTER:
p = 0;
break;
case Archive::POINTER:
archive.read(p);
break;
case Archive::INSTANCE:
if (ref_tag.type_name.isEmpty()) {
registry::load_non_virtual_pointer<Archive,T>(archive, p);
} else {
typename registry::TypeRegistry<Archive, T>::type_info type_data = get_type_info<Archive, T>(ref_tag.type_name);
if (type_data.load_func == 0) {
throw unregistered_type();
} else {
type_data.load_func(archive, p);
}
}
break;
}
archive.readReferenceEndTag(ref_tag.kind);
return archive;
}
template<class Archive, class T>
typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, T *&p)
{
return archive << p;
}
template<class Archive, class T>
typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive &archive, T *&p)
{
return archive >> p;
} }
template<class Archive, class T> template<class Archive, class T>
@@ -175,32 +101,6 @@ typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive
return archive >> f; return archive >> f;
} }
template<class Archive>
inline Archive &operator<<(Archive &archive, void (*f)(Archive &))
{
f(archive);
return archive;
}
template<class Archive>
inline Archive &operator>>(Archive &archive, void (*f)(Archive &))
{
f(archive);
return archive;
}
template<class Archive>
typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, void (*f)(Archive &))
{
return archive << f;
}
template<class Archive>
typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive &archive, void (*f)(Archive &))
{
return archive >> f;
}
template<class Archive> template<class Archive>
inline Archive &operator<<(Archive &archive, const Tag &tag) inline Archive &operator<<(Archive &archive, const Tag &tag)
{ {
@@ -311,7 +211,7 @@ template<class Archive, typename T>
Archive &operator<<(Archive &archive, const Attr<T> &attr) Archive &operator<<(Archive &archive, const Attr<T> &attr)
{ {
archive.beginAttribute(attr); archive.beginAttribute(attr);
archive << *attr.getValue(); save(archive, *attr.getValue(), attr.getParameters());
archive.endAttribute(attr); archive.endAttribute(attr);
return archive; return archive;
} }
@@ -336,10 +236,23 @@ typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive
} }
template<class Archive, class U, typename T> template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetterAttr<U, T> &attr) typename std::enable_if<!std::is_abstract<U>::value, Archive &>::type
operator<<(Archive &archive, const GetterAttr<U, T> &attr)
{
if (!((attr.getObject().*(attr.getGetter()))() == (U().*(attr.getGetter()))())) {
archive.beginAttribute(attr);
save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr);
}
return archive;
}
template<class Archive, class U, typename T>
typename std::enable_if<std::is_abstract<U>::value, Archive &>::type
operator<<(Archive &archive, const GetterAttr<U, T> &attr)
{ {
archive.beginAttribute(attr); archive.beginAttribute(attr);
archive << (attr.getObject().*(attr.getGetter()))(); save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr); archive.endAttribute(attr);
return archive; return archive;
} }
@@ -358,7 +271,7 @@ operator<<(Archive &archive, const GetterSetterAttr<U, T, V> &attr)
{ {
if (!((attr.getObject().*(attr.getGetter()))() == (U().*(attr.getGetter()))())) { if (!((attr.getObject().*(attr.getGetter()))() == (U().*(attr.getGetter()))())) {
archive.beginAttribute(attr); archive.beginAttribute(attr);
archive << (attr.getObject().*(attr.getGetter()))(); save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr); archive.endAttribute(attr);
} }
return archive; return archive;
@@ -370,7 +283,7 @@ typename std::enable_if<std::is_abstract<U>::value, Archive &>::type
operator<<(Archive &archive, const GetterSetterAttr<U, T, V> &attr) operator<<(Archive &archive, const GetterSetterAttr<U, T, V> &attr)
{ {
archive.beginAttribute(attr); archive.beginAttribute(attr);
archive << (attr.getObject().*(attr.getGetter()))(); save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr); archive.endAttribute(attr);
return archive; return archive;
} }
@@ -398,7 +311,7 @@ template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetFuncAttr<U, T> &attr) Archive &operator<<(Archive &archive, const GetFuncAttr<U, T> &attr)
{ {
archive.beginAttribute(attr); archive.beginAttribute(attr);
archive << ((*attr.getGetFunc())(attr.getObject())); save(archive, ((*attr.getGetFunc())(attr.getObject())), attr.getParameters());
archive.endAttribute(attr); archive.endAttribute(attr);
return archive; return archive;
} }
@@ -414,7 +327,7 @@ template<class Archive, class U, typename T, typename V>
Archive &operator<<(Archive &archive, const GetSetFuncAttr<U, T, V> &attr) Archive &operator<<(Archive &archive, const GetSetFuncAttr<U, T, V> &attr)
{ {
archive.beginAttribute(attr); archive.beginAttribute(attr);
archive << ((*attr.getGetFunc())(attr.getObject())); save(archive, ((*attr.getGetFunc())(attr.getObject())), attr.getParameters());
archive.endAttribute(attr); archive.endAttribute(attr);
return archive; return archive;
} }
@@ -442,7 +355,7 @@ template<class Archive, typename T>
Archive &operator<<(Archive &archive, const Ref<T *> &ref) Archive &operator<<(Archive &archive, const Ref<T *> &ref)
{ {
archive.beginReference(ref); archive.beginReference(ref);
archive << *ref.getValue(); save(archive, *ref.getValue(), ref.getParameters());
archive.endReference(ref); archive.endReference(ref);
return archive; return archive;
} }
@@ -451,7 +364,7 @@ template<class Archive, typename T>
Archive &operator<<(Archive &archive, const Ref<T * const> &ref) Archive &operator<<(Archive &archive, const Ref<T * const> &ref)
{ {
archive.beginReference(ref); archive.beginReference(ref);
archive << *ref.getValue(); save(archive, *ref.getValue(), ref.getParameters());
archive.endReference(ref); archive.endReference(ref);
return archive; return archive;
} }
@@ -467,7 +380,7 @@ template<class Archive, typename T>
typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, const Ref<T *> &ref) typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, const Ref<T *> &ref)
{ {
archive.beginReference(ref); archive.beginReference(ref);
archive << *ref.getValue(); save(archive, *ref.getValue(), ref.getParameters());
archive.endReference(ref); archive.endReference(ref);
return archive; return archive;
} }
@@ -482,7 +395,7 @@ template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetterRef<U, T> &ref) Archive &operator<<(Archive &archive, const GetterRef<U, T> &ref)
{ {
archive.beginReference(ref); archive.beginReference(ref);
archive << (ref.getObject().*(ref.getGetter()))(); save(archive, (ref.getObject().*(ref.getGetter()))(), ref.getParameters());
archive.endReference(ref); archive.endReference(ref);
return archive; return archive;
} }
@@ -498,7 +411,7 @@ template<class Archive, class U, typename T, typename V>
Archive &operator<<(Archive &archive, const GetterSetterRef<U, T, V> &ref) Archive &operator<<(Archive &archive, const GetterSetterRef<U, T, V> &ref)
{ {
archive.beginReference(ref); archive.beginReference(ref);
archive << (ref.getObject().*(ref.getGetter()))(); save(archive, (ref.getObject().*(ref.getGetter()))(), ref.getParameters());
archive.endReference(ref); archive.endReference(ref);
return archive; return archive;
} }
@@ -526,7 +439,7 @@ template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetFuncRef<U, T> &ref) Archive &operator<<(Archive &archive, const GetFuncRef<U, T> &ref)
{ {
archive.beginReference(ref); archive.beginReference(ref);
archive << ref.getGetFunc()(ref.getObject()); save(archive, ref.getGetFunc()(ref.getObject()), ref.getParameters());
archive.endReference(ref); archive.endReference(ref);
return archive; return archive;
} }
@@ -542,7 +455,7 @@ template<class Archive, class U, typename T, typename V>
Archive &operator<<(Archive &archive, const GetSetFuncRef<U, T, V> &ref) Archive &operator<<(Archive &archive, const GetSetFuncRef<U, T, V> &ref)
{ {
archive.beginReference(ref); archive.beginReference(ref);
archive << ref.getGetFunc()(ref.getObject()); save(archive, ref.getGetFunc()(ref.getObject()), ref.getParameters());
archive.endReference(ref); archive.endReference(ref);
return archive; return archive;
} }

View File

@@ -31,6 +31,7 @@
#ifndef QARK_SERIALIZE_BASIC_H #ifndef QARK_SERIALIZE_BASIC_H
#define QARK_SERIALIZE_BASIC_H #define QARK_SERIALIZE_BASIC_H
#include "parameters.h"
#include "qstringparser/qstringparser.h" #include "qstringparser/qstringparser.h"
#include <QString> #include <QString>
@@ -42,12 +43,12 @@
#define QARK_BASIC_SAVELOAD(TYPE) \ #define QARK_BASIC_SAVELOAD(TYPE) \
template<class Archive> \ template<class Archive> \
inline void save(Archive &archive, TYPE v) \ inline void save(Archive &archive, TYPE v, const Parameters &) \
{ \ { \
archive.write(v); \ archive.write(v); \
} \ } \
template<class Archive> \ template<class Archive> \
inline void load(Archive &archive, TYPE &v) \ inline void load(Archive &archive, TYPE &v, const Parameters &) \
{ \ { \
archive.read(&v); \ archive.read(&v); \
} }
@@ -79,13 +80,13 @@ QARK_BASIC_SAVELOAD(QString)
// QPointF // QPointF
template<class Archive> template<class Archive>
inline void save(Archive &archive, const QPointF &point) inline void save(Archive &archive, const QPointF &point, const Parameters &)
{ {
archive.write(QString(QStringLiteral("x:%1;y:%2")).arg(point.x()).arg(point.y())); archive.write(QString(QStringLiteral("x:%1;y:%2")).arg(point.x()).arg(point.y()));
} }
template<class Archive> template<class Archive>
inline void load(Archive &archive, QPointF &point) inline void load(Archive &archive, QPointF &point, const Parameters &)
{ {
QString s; QString s;
archive.read(&s); archive.read(&s);
@@ -98,13 +99,13 @@ inline void load(Archive &archive, QPointF &point)
// QRectF // QRectF
template<class Archive> template<class Archive>
inline void save(Archive &archive, const QRectF &rect) inline void save(Archive &archive, const QRectF &rect, const Parameters &)
{ {
archive.write(QString(QStringLiteral("x:%1;y:%2;w:%3;h:%4")).arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height())); archive.write(QString(QStringLiteral("x:%1;y:%2;w:%3;h:%4")).arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height()));
} }
template<class Archive> template<class Archive>
inline void load(Archive &archive, QRectF &point) inline void load(Archive &archive, QRectF &point, const Parameters &)
{ {
QString s; QString s;
archive.read(&s); archive.read(&s);
@@ -117,13 +118,13 @@ inline void load(Archive &archive, QRectF &point)
// QDateTime // QDateTime
template<class Archive> template<class Archive>
inline void save(Archive &archive, const QDateTime &date_time) inline void save(Archive &archive, const QDateTime &date_time, const Parameters &)
{ {
archive << date_time.toMSecsSinceEpoch(); archive << date_time.toMSecsSinceEpoch();
} }
template<class Archive> template<class Archive>
inline void load(Archive &archive, QDateTime &date_time) inline void load(Archive &archive, QDateTime &date_time, const Parameters &)
{ {
qint64 t; qint64 t;
archive >> t; archive >> t;

View File

@@ -31,31 +31,22 @@
#ifndef QARK_SERIALIZE_CONTAINER_H #ifndef QARK_SERIALIZE_CONTAINER_H
#define QARK_SERIALIZE_CONTAINER_H #define QARK_SERIALIZE_CONTAINER_H
#include "flag.h" #include "parameters.h"
#include <QList> #include <QList>
#include <QHash> #include <QHash>
namespace qark { namespace qark {
namespace impl { static Flag ENFORCE_REFERENCED_ITEMS;
static Flag container_item_ref_flag;
}
template<class Archive>
inline void ref_item(Archive &archive)
{
archive.setFlag(impl::container_item_ref_flag);
}
// QList // QList
template<class Archive, class T> template<class Archive, class T>
inline void save(Archive &archive, const QList<T> &list) inline void save(Archive &archive, const QList<T> &list, const Parameters &)
{ {
archive << tag("qlist"); archive << tag("qlist");
archive.clearFlag(impl::container_item_ref_flag);
foreach (const T &t, list) { foreach (const T &t, list) {
archive << attr(QStringLiteral("item"), t); archive << attr(QStringLiteral("item"), t);
} }
@@ -63,10 +54,10 @@ inline void save(Archive &archive, const QList<T> &list)
} }
template<class Archive, class T> template<class Archive, class T>
inline void save(Archive &archive, const QList<T *> &list) inline void save(Archive &archive, const QList<T *> &list, const Parameters &parameters)
{ {
archive << tag("qlist"); archive << tag("qlist");
if (archive.takeFlag(impl::container_item_ref_flag)) { if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
foreach (const T *t, list) { foreach (const T *t, list) {
archive << ref(QStringLiteral("item"), t); archive << ref(QStringLiteral("item"), t);
} }
@@ -79,7 +70,7 @@ inline void save(Archive &archive, const QList<T *> &list)
} }
template<class Archive, class T> template<class Archive, class T>
inline void load(Archive &archive, QList<T> &list) inline void load(Archive &archive, QList<T> &list, const Parameters &)
{ {
archive >> tag(QStringLiteral("qlist")); archive >> tag(QStringLiteral("qlist"));
archive >> attr<QList<T>, const T &>(QStringLiteral("item"), list, &QList<T>::append); archive >> attr<QList<T>, const T &>(QStringLiteral("item"), list, &QList<T>::append);
@@ -87,10 +78,10 @@ inline void load(Archive &archive, QList<T> &list)
} }
template<class Archive, class T> template<class Archive, class T>
inline void load(Archive &archive, QList<T *> &list) inline void load(Archive &archive, QList<T *> &list, const Parameters &parameters)
{ {
archive >> tag(QStringLiteral("qlist")); archive >> tag(QStringLiteral("qlist"));
if (archive.takeFlag(impl::container_item_ref_flag)) { if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
// why does the following line not compile but the line below selects the correct function? // why does the following line not compile but the line below selects the correct function?
//archive >> ref<QList<T *>, T * const &>("item", list, &QList<T *>::append); //archive >> ref<QList<T *>, T * const &>("item", list, &QList<T *>::append);
archive >> ref(QStringLiteral("item"), list, &QList<T *>::append); archive >> ref(QStringLiteral("item"), list, &QList<T *>::append);
@@ -104,10 +95,9 @@ inline void load(Archive &archive, QList<T *> &list)
// QSet // QSet
template<class Archive, class T> template<class Archive, class T>
inline void save(Archive &archive, const QSet<T> &set) inline void save(Archive &archive, const QSet<T> &set, const Parameters &)
{ {
archive << tag("qset"); archive << tag("qset");
archive.clearFlag(impl::container_item_ref_flag);
foreach (const T &t, set) { foreach (const T &t, set) {
archive << attr(QStringLiteral("item"), t); archive << attr(QStringLiteral("item"), t);
} }
@@ -115,10 +105,10 @@ inline void save(Archive &archive, const QSet<T> &set)
} }
template<class Archive, class T> template<class Archive, class T>
inline void save(Archive &archive, const QSet<T *> &set) inline void save(Archive &archive, const QSet<T *> &set, const Parameters &parameters)
{ {
archive << tag("qset"); archive << tag("qset");
if (archive.takeFlag(impl::container_item_ref_flag)) { if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
foreach (const T *t, set) { foreach (const T *t, set) {
archive << ref(QStringLiteral("item"), t); archive << ref(QStringLiteral("item"), t);
} }
@@ -140,7 +130,7 @@ void insertIntoSet(QSet<T> &set, const T &t) {
} }
template<class Archive, class T> template<class Archive, class T>
inline void load(Archive &archive, QSet<T> &set) inline void load(Archive &archive, QSet<T> &set, const Parameters &)
{ {
archive >> tag(QStringLiteral("qset")); archive >> tag(QStringLiteral("qset"));
archive >> attr<QSet<T>, const T &>(QStringLiteral("item"), set, &impl::insertIntoSet<T>); archive >> attr<QSet<T>, const T &>(QStringLiteral("item"), set, &impl::insertIntoSet<T>);
@@ -148,10 +138,10 @@ inline void load(Archive &archive, QSet<T> &set)
} }
template<class Archive, class T> template<class Archive, class T>
inline void load(Archive &archive, QSet<T *> &set) inline void load(Archive &archive, QSet<T *> &set, const Parameters &parameters)
{ {
archive >> tag(QStringLiteral("qset")); archive >> tag(QStringLiteral("qset"));
if (archive.takeFlag(impl::container_item_ref_flag)) { if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
archive >> ref(QStringLiteral("item"), set, &impl::insertIntoSet<T *>); archive >> ref(QStringLiteral("item"), set, &impl::insertIntoSet<T *>);
} else { } else {
archive >> attr<QSet<T *>, T * const &>(QStringLiteral("item"), set, &impl::insertIntoSet<T *>); archive >> attr<QSet<T *>, T * const &>(QStringLiteral("item"), set, &impl::insertIntoSet<T *>);
@@ -177,7 +167,7 @@ public:
} }
template<class Archive, class KEY, class VALUE> template<class Archive, class KEY, class VALUE>
inline void save(Archive &archive, const impl::KeyValuePair<KEY, VALUE> &pair) inline void save(Archive &archive, const impl::KeyValuePair<KEY, VALUE> &pair, const Parameters &)
{ {
archive << tag(QStringLiteral("pair")) archive << tag(QStringLiteral("pair"))
<< attr(QStringLiteral("key"), pair._key) << attr(QStringLiteral("key"), pair._key)
@@ -186,7 +176,7 @@ inline void save(Archive &archive, const impl::KeyValuePair<KEY, VALUE> &pair)
} }
template<class Archive, class KEY, class VALUE> template<class Archive, class KEY, class VALUE>
inline void load(Archive &archive, impl::KeyValuePair<KEY, VALUE> &pair) inline void load(Archive &archive, impl::KeyValuePair<KEY, VALUE> &pair, const Parameters &)
{ {
archive >> tag(QStringLiteral("pair")) archive >> tag(QStringLiteral("pair"))
>> attr(QStringLiteral("key"), pair._key) >> attr(QStringLiteral("key"), pair._key)
@@ -195,7 +185,7 @@ inline void load(Archive &archive, impl::KeyValuePair<KEY, VALUE> &pair)
} }
template<class Archive, class KEY, class VALUE> template<class Archive, class KEY, class VALUE>
inline void save(Archive &archive, const QHash<KEY, VALUE> &hash) inline void save(Archive &archive, const QHash<KEY, VALUE> &hash, const Parameters &)
{ {
archive << tag(QStringLiteral("qhash")); archive << tag(QStringLiteral("qhash"));
for (typename QHash<KEY, VALUE>::const_iterator it = hash.begin(); it != hash.end(); ++it) { for (typename QHash<KEY, VALUE>::const_iterator it = hash.begin(); it != hash.end(); ++it) {
@@ -216,7 +206,7 @@ inline void keyValuePairInsert(QHash<KEY, VALUE> &hash, const KeyValuePair<KEY,
} }
template<class Archive, class KEY, class VALUE> template<class Archive, class KEY, class VALUE>
inline void load(Archive &archive, QHash<KEY, VALUE> &hash) inline void load(Archive &archive, QHash<KEY, VALUE> &hash, const Parameters &)
{ {
archive >> tag(QStringLiteral("qhash")); archive >> tag(QStringLiteral("qhash"));
archive >> attr(QStringLiteral("item"), hash, &impl::keyValuePairInsert<KEY, VALUE>); archive >> attr(QStringLiteral("item"), hash, &impl::keyValuePairInsert<KEY, VALUE>);

View File

@@ -31,6 +31,8 @@
#ifndef QARK_SERIALIZE_ENUM_H #ifndef QARK_SERIALIZE_ENUM_H
#define QARK_SERIALIZE_ENUM_H #define QARK_SERIALIZE_ENUM_H
#include "parameters.h"
#include <type_traits> #include <type_traits>
namespace qark { namespace qark {
@@ -38,13 +40,13 @@ namespace qark {
#if 0 // ambigous with default implementation in access.h #if 0 // ambigous with default implementation in access.h
template<class Archive, typename T> template<class Archive, typename T>
inline typename std::enable_if<std::is_enum<T>::value, void>::type save(Archive &archive, const T &value) inline typename std::enable_if<std::is_enum<T>::value, void>::type save(Archive &archive, const T &value, const Parameters &)
{ {
archive.write((int) value); archive.write((int) value);
} }
template<class Archive, typename T> template<class Archive, typename T>
inline typename std::enable_if<std::is_enum<T>::value, void>::type load(Archive &archive, T &value) inline typename std::enable_if<std::is_enum<T>::value, void>::type load(Archive &archive, T &value, const Parameters &)
{ {
int i = 0; int i = 0;
archive.read(&i); archive.read(&i);
@@ -55,12 +57,12 @@ inline typename std::enable_if<std::is_enum<T>::value, void>::type load(Archive
#define QARK_SERIALIZE_ENUM(ENUM) \ #define QARK_SERIALIZE_ENUM(ENUM) \
template<class Archive> \ template<class Archive> \
inline void save(Archive &archive, const ENUM &e) \ inline void save(Archive &archive, const ENUM &e, const Parameters &) \
{ \ { \
archive.write((int) e); \ archive.write((int) e); \
} \ } \
template<class Archive> \ template<class Archive> \
inline void load(Archive &archive, ENUM &e) \ inline void load(Archive &archive, ENUM &e, const Parameters &) \
{ \ { \
int i = 0; \ int i = 0; \
archive.read(&i); \ archive.read(&i); \
@@ -68,13 +70,13 @@ inline typename std::enable_if<std::is_enum<T>::value, void>::type load(Archive
} }
template<class Archive, typename T> template<class Archive, typename T>
inline void save(Archive &archive, const QFlags<T> &flags) inline void save(Archive &archive, const QFlags<T> &flags, const Parameters &)
{ {
archive.write((typename QFlags<T>::Int) flags); archive.write((typename QFlags<T>::Int) flags);
} }
template<class Archive, typename T> template<class Archive, typename T>
inline void load(Archive &archive, QFlags<T> &flags) inline void load(Archive &archive, QFlags<T> &flags, const Parameters &)
{ {
typename QFlags<T>::Int i = 0; typename QFlags<T>::Int i = 0;
archive.read(&i); archive.read(&i);

View File

@@ -0,0 +1,98 @@
/***************************************************************************
**
** Copyright (C) 2015 Jochen Becher
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef QARK_SERIALIZE_POINTER_H
#define QARK_SERIALIZE_POINTER_H
#include "typeregistry.h"
namespace qark {
template<class Archive, class T>
inline void save(Archive &archive, T *p, const Parameters &)
{
if (p) {
if (archive.isReference(p)) {
archive.beginPointer();
archive.write(p);
archive.endPointer();
} else {
if (typeid(*p) == typeid(T)) {
archive.beginInstance();
registry::save_pointer<Archive, T, T>(archive, p);
archive.endInstance();
} else {
archive.beginInstance(get_type_uid(*p));
typename registry::TypeRegistry<Archive, T>::type_info type_data = get_type_info<Archive, T>(*p);
if (type_data.save_func == 0) {
throw unregistered_type();
} else {
type_data.save_func(archive, p);
}
archive.endInstance();
}
}
} else {
archive.beginNullPointer();
archive.endNullPointer();
}
}
template<class Archive, class T>
void load(Archive &archive, T *&p, const Parameters &)
{
typename Archive::ReferenceTag ref_tag = archive.readReferenceTag();
switch (ref_tag.kind) {
case Archive::NULLPOINTER:
p = 0;
break;
case Archive::POINTER:
archive.read(p);
break;
case Archive::INSTANCE:
if (ref_tag.type_name.isEmpty()) {
registry::load_non_virtual_pointer<Archive,T>(archive, p);
} else {
typename registry::TypeRegistry<Archive, T>::type_info type_data = get_type_info<Archive, T>(ref_tag.type_name);
if (type_data.load_func == 0) {
throw unregistered_type();
} else {
type_data.load_func(archive, p);
}
}
break;
}
archive.readReferenceEndTag(ref_tag.kind);
}
}
#endif // QARK_SERIALIZE_POINTER_H

View File

@@ -32,6 +32,7 @@
#define QARK_TAG_H #define QARK_TAG_H
#include "typeregistry.h" #include "typeregistry.h"
#include "parameters.h"
#include <QString> #include <QString>
@@ -45,10 +46,19 @@ public:
{ {
} }
Tag(const QString &qualified_name, const Parameters &parameters)
: _qualified_name(qualified_name),
_parameters(parameters)
{
}
const QString &getQualifiedName() const { return _qualified_name; } const QString &getQualifiedName() const { return _qualified_name; }
Parameters getParameters() const { return _parameters; }
private: private:
QString _qualified_name; QString _qualified_name;
Parameters _parameters;
}; };
@@ -57,12 +67,18 @@ class Object :
public Tag public Tag
{ {
public: public:
explicit Object(const QString &qualified_name, T *object) Object(const QString &qualified_name, T *object)
: Tag(qualified_name), : Tag(qualified_name),
_object(object) _object(object)
{ {
} }
Object(const QString &qualified_name, T *object, const Parameters &parameters)
: Tag(qualified_name, parameters),
_object(object)
{
}
T *getObject() const { return _object; } T *getObject() const { return _object; }
private: private:
@@ -75,28 +91,61 @@ inline Tag tag(const QString &qualified_name)
return Tag(qualified_name); return Tag(qualified_name);
} }
inline Tag tag(const QString &qualified_name, const Parameters &parameters)
{
return Tag(qualified_name, parameters);
}
inline Tag tag(const char *qualified_name) inline Tag tag(const char *qualified_name)
{ {
return Tag(QLatin1String(qualified_name)); return Tag(QLatin1String(qualified_name));
} }
inline Tag tag(const char *qualified_name, const Parameters &parameters)
{
return Tag(QLatin1String(qualified_name), parameters);
}
template<class T> template<class T>
inline Object<T> tag(T &object) inline Object<T> tag(T &object)
{ {
return Object<T>(get_type_uid<T>(), &object); return Object<T>(get_type_uid<T>(), &object);
} }
template<class T>
inline Object<T> tag(T &object, const Parameters &parameters)
{
return Object<T>(get_type_uid<T>(), &object, parameters);
}
template<class T> template<class T>
inline Object<T> tag(const QString &qualified_name, T &object) inline Object<T> tag(const QString &qualified_name, T &object)
{ {
return Object<T>(qualified_name, &object); return Object<T>(qualified_name, &object);
} }
template<class T>
inline Object<T> tag(const QString &qualified_name, T &object, const Parameters &parameters)
{
return Object<T>(qualified_name, &object, parameters);
}
class End { class End {
public: public:
explicit End() { } explicit End()
{
}
explicit End(const Parameters &parameters)
: _parameters(parameters)
{
}
Parameters getParameters() const { return _parameters; }
private:
Parameters _parameters;
}; };
inline End end() inline End end()
@@ -104,6 +153,10 @@ inline End end()
return End(); return End();
} }
inline End end(const Parameters &parameters)
{
return End(parameters);
}
} }

View File

@@ -31,6 +31,8 @@
#ifndef QARK_TYPEREGISTRY_H #ifndef QARK_TYPEREGISTRY_H
#define QARK_TYPEREGISTRY_H #define QARK_TYPEREGISTRY_H
#include "parameters.h"
#include "qmt/infrastructure/qmtassert.h" #include "qmt/infrastructure/qmtassert.h"
#include <exception> #include <exception>
@@ -219,7 +221,7 @@ template<class Archive, class BASE, class DERIVED>
Archive &save_pointer(Archive &ar, BASE * const &p) Archive &save_pointer(Archive &ar, BASE * const &p)
{ {
DERIVED &t = dynamic_cast<DERIVED &>(*p); DERIVED &t = dynamic_cast<DERIVED &>(*p);
ar << t; save(ar, t, Parameters());
return ar; return ar;
} }
@@ -227,7 +229,7 @@ template<class Archive, class BASE, class DERIVED>
Archive &load_pointer(Archive &ar, BASE *&p) Archive &load_pointer(Archive &ar, BASE *&p)
{ {
DERIVED *t = new DERIVED(); DERIVED *t = new DERIVED();
ar >> *t; load(ar, *t, Parameters());
p = t; p = t;
return ar; return ar;
} }

View File

@@ -6,6 +6,7 @@ HEADERS += \
$$PWD/inc/qark/baseclass.h \ $$PWD/inc/qark/baseclass.h \
$$PWD/inc/qark/flag.h \ $$PWD/inc/qark/flag.h \
$$PWD/inc/qark/friend_access.h \ $$PWD/inc/qark/friend_access.h \
$$PWD/inc/qark/parameters.h \
$$PWD/inc/qark/qxmlinarchive.h \ $$PWD/inc/qark/qxmlinarchive.h \
$$PWD/inc/qark/qxmloutarchive.h \ $$PWD/inc/qark/qxmloutarchive.h \
$$PWD/inc/qark/reference.h \ $$PWD/inc/qark/reference.h \
@@ -13,6 +14,7 @@ HEADERS += \
$$PWD/inc/qark/serialize_basic.h \ $$PWD/inc/qark/serialize_basic.h \
$$PWD/inc/qark/serialize_container.h \ $$PWD/inc/qark/serialize_container.h \
$$PWD/inc/qark/serialize_enum.h \ $$PWD/inc/qark/serialize_enum.h \
$$PWD/inc/qark/serialize_pointer.h \
$$PWD/inc/qark/tag.h \ $$PWD/inc/qark/tag.h \
$$PWD/inc/qark/typeregistry.h \ $$PWD/inc/qark/typeregistry.h \
$$PWD/inc/qark/impl/loadingrefmap.h \ $$PWD/inc/qark/impl/loadingrefmap.h \

View File

@@ -45,7 +45,8 @@ SOURCES += $$PWD/ipcserverinterface.cpp \
$$PWD/fixitcontainer.cpp \ $$PWD/fixitcontainer.cpp \
$$PWD/requestdiagnosticsmessage.cpp \ $$PWD/requestdiagnosticsmessage.cpp \
$$PWD/registerunsavedfilesforeditormessage.cpp \ $$PWD/registerunsavedfilesforeditormessage.cpp \
$$PWD/unregisterunsavedfilesforeditormessage.cpp $$PWD/unregisterunsavedfilesforeditormessage.cpp \
$$PWD/updatetranslationunitsforeditormessage.cpp
HEADERS += \ HEADERS += \
$$PWD/ipcserverinterface.h \ $$PWD/ipcserverinterface.h \
@@ -85,6 +86,7 @@ HEADERS += \
$$PWD/fixitcontainer.h \ $$PWD/fixitcontainer.h \
$$PWD/requestdiagnosticsmessage.h \ $$PWD/requestdiagnosticsmessage.h \
$$PWD/registerunsavedfilesforeditormessage.h \ $$PWD/registerunsavedfilesforeditormessage.h \
$$PWD/unregisterunsavedfilesforeditormessage.h $$PWD/unregisterunsavedfilesforeditormessage.h \
$$PWD/updatetranslationunitsforeditormessage.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols

View File

@@ -44,7 +44,6 @@
#endif #endif
namespace ClangBackEnd { namespace ClangBackEnd {
CMBIPC_EXPORT void registerTypes();
enum class DiagnosticSeverity // one to one mapping of the clang enum numbers enum class DiagnosticSeverity // one to one mapping of the clang enum numbers
{ {

View File

@@ -48,95 +48,53 @@
#include "sourcerangecontainer.h" #include "sourcerangecontainer.h"
#include "translationunitdoesnotexistmessage.h" #include "translationunitdoesnotexistmessage.h"
#include "unregisterunsavedfilesforeditormessage.h" #include "unregisterunsavedfilesforeditormessage.h"
#include "updatetranslationunitsforeditormessage.h"
#include <QDataStream> #include <QDataStream>
template <typename T>
static void registerMetaType()
{
qRegisterMetaType<T>();
qRegisterMetaTypeStreamOperators<T>();
QMetaType::registerComparators<T>();
}
namespace ClangBackEnd { namespace ClangBackEnd {
void Messages::registerMessages() void Messages::registerMessages()
{ {
qRegisterMetaType<EndMessage>(); // Messages
qRegisterMetaTypeStreamOperators<EndMessage>(); registerMetaType<AliveMessage>();
QMetaType::registerComparators<EndMessage>(); registerMetaType<EchoMessage>();
registerMetaType<EndMessage>();
qRegisterMetaType<AliveMessage>(); registerMetaType<RegisterTranslationUnitForEditorMessage>();
qRegisterMetaTypeStreamOperators<AliveMessage>(); registerMetaType<UpdateTranslationUnitsForEditorMessage>();
QMetaType::registerComparators<AliveMessage>(); registerMetaType<UnregisterTranslationUnitsForEditorMessage>();
qRegisterMetaType<EchoMessage>(); registerMetaType<RegisterUnsavedFilesForEditorMessage>();
qRegisterMetaTypeStreamOperators<EchoMessage>(); registerMetaType<UnregisterUnsavedFilesForEditorMessage>();
qRegisterMetaType<RegisterTranslationUnitForEditorMessage>(); registerMetaType<RegisterProjectPartsForEditorMessage>();
qRegisterMetaTypeStreamOperators<RegisterTranslationUnitForEditorMessage>(); registerMetaType<UnregisterProjectPartsForEditorMessage>();
QMetaType::registerComparators<RegisterTranslationUnitForEditorMessage>();
qRegisterMetaType<FileContainer>(); registerMetaType<RequestDiagnosticsMessage>();
qRegisterMetaTypeStreamOperators<FileContainer>(); registerMetaType<DiagnosticsChangedMessage>();
QMetaType::registerComparators<FileContainer>();
qRegisterMetaType<UnregisterTranslationUnitsForEditorMessage>(); registerMetaType<CompleteCodeMessage>();
qRegisterMetaTypeStreamOperators<UnregisterTranslationUnitsForEditorMessage>(); registerMetaType<CodeCompletedMessage>();
QMetaType::registerComparators<UnregisterTranslationUnitsForEditorMessage>(); registerMetaType<CodeCompletion>();
qRegisterMetaType<CompleteCodeMessage>(); registerMetaType<TranslationUnitDoesNotExistMessage>();
qRegisterMetaTypeStreamOperators<CompleteCodeMessage>(); registerMetaType<ProjectPartsDoNotExistMessage>();
QMetaType::registerComparators<CompleteCodeMessage>();
qRegisterMetaType<CodeCompletion>(); // Containers
qRegisterMetaTypeStreamOperators<CodeCompletion>(); registerMetaType<DiagnosticContainer>();
QMetaType::registerComparators<CodeCompletion>(); registerMetaType<FileContainer>();
registerMetaType<ProjectPartContainer>();
qRegisterMetaType<CodeCompletedMessage>(); registerMetaType<SourceLocationContainer>();
qRegisterMetaTypeStreamOperators<CodeCompletedMessage>(); registerMetaType<SourceRangeContainer>();
QMetaType::registerComparators<CodeCompletedMessage>();
qRegisterMetaType<RegisterProjectPartsForEditorMessage>();
qRegisterMetaTypeStreamOperators<RegisterProjectPartsForEditorMessage>();
QMetaType::registerComparators<RegisterProjectPartsForEditorMessage>();
qRegisterMetaType<ProjectPartContainer>();
qRegisterMetaTypeStreamOperators<ProjectPartContainer>();
QMetaType::registerComparators<ProjectPartContainer>();
qRegisterMetaType<UnregisterProjectPartsForEditorMessage>();
qRegisterMetaTypeStreamOperators<UnregisterProjectPartsForEditorMessage>();
QMetaType::registerComparators<UnregisterProjectPartsForEditorMessage>();
qRegisterMetaType<TranslationUnitDoesNotExistMessage>();
qRegisterMetaTypeStreamOperators<TranslationUnitDoesNotExistMessage>();
QMetaType::registerComparators<TranslationUnitDoesNotExistMessage>();
qRegisterMetaType<ProjectPartsDoNotExistMessage>();
qRegisterMetaTypeStreamOperators<ProjectPartsDoNotExistMessage>();
QMetaType::registerComparators<ProjectPartsDoNotExistMessage>();
qRegisterMetaType<DiagnosticsChangedMessage>();
qRegisterMetaTypeStreamOperators<DiagnosticsChangedMessage>();
QMetaType::registerComparators<DiagnosticsChangedMessage>();
qRegisterMetaType<DiagnosticContainer>();
qRegisterMetaTypeStreamOperators<DiagnosticContainer>();
QMetaType::registerComparators<DiagnosticContainer>();
qRegisterMetaType<SourceLocationContainer>();
qRegisterMetaTypeStreamOperators<SourceLocationContainer>();
QMetaType::registerComparators<SourceLocationContainer>();
qRegisterMetaType<SourceRangeContainer>();
qRegisterMetaTypeStreamOperators<SourceRangeContainer>();
QMetaType::registerComparators<SourceRangeContainer>();
qRegisterMetaType<RequestDiagnosticsMessage>();
qRegisterMetaTypeStreamOperators<RequestDiagnosticsMessage>();
QMetaType::registerComparators<RequestDiagnosticsMessage>();
qRegisterMetaType<RegisterUnsavedFilesForEditorMessage>();
qRegisterMetaTypeStreamOperators<RegisterUnsavedFilesForEditorMessage>();
QMetaType::registerComparators<RegisterUnsavedFilesForEditorMessage>();
qRegisterMetaType<UnregisterUnsavedFilesForEditorMessage>();
qRegisterMetaTypeStreamOperators<UnregisterUnsavedFilesForEditorMessage>();
QMetaType::registerComparators<UnregisterUnsavedFilesForEditorMessage>();
} }
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -37,6 +37,7 @@ namespace ClangBackEnd {
class IpcServerInterface; class IpcServerInterface;
class RegisterTranslationUnitForEditorMessage; class RegisterTranslationUnitForEditorMessage;
class UpdateTranslationUnitsForEditorMessage;
class RegisterProjectPartsForEditorMessage; class RegisterProjectPartsForEditorMessage;
class UnregisterTranslationUnitsForEditorMessage; class UnregisterTranslationUnitsForEditorMessage;
class UnregisterProjectPartsForEditorMessage; class UnregisterProjectPartsForEditorMessage;

View File

@@ -38,6 +38,7 @@
#include "registerunsavedfilesforeditormessage.h" #include "registerunsavedfilesforeditormessage.h"
#include "requestdiagnosticsmessage.h" #include "requestdiagnosticsmessage.h"
#include "unregisterunsavedfilesforeditormessage.h" #include "unregisterunsavedfilesforeditormessage.h"
#include "updatetranslationunitsforeditormessage.h"
#include <QDebug> #include <QDebug>
#include <QVariant> #include <QVariant>
@@ -48,6 +49,7 @@ void IpcServerInterface::dispatch(const QVariant &message)
{ {
static const int endMessageType = QMetaType::type("ClangBackEnd::EndMessage"); static const int endMessageType = QMetaType::type("ClangBackEnd::EndMessage");
static const int registerTranslationUnitsForEditorMessageType = QMetaType::type("ClangBackEnd::RegisterTranslationUnitForEditorMessage"); static const int registerTranslationUnitsForEditorMessageType = QMetaType::type("ClangBackEnd::RegisterTranslationUnitForEditorMessage");
static const int updateTranslationUnitsForEditorMessageType = QMetaType::type("ClangBackEnd::UpdateTranslationUnitsForEditorMessage");
static const int unregisterTranslationUnitsForEditorMessageType = QMetaType::type("ClangBackEnd::UnregisterTranslationUnitsForEditorMessage"); static const int unregisterTranslationUnitsForEditorMessageType = QMetaType::type("ClangBackEnd::UnregisterTranslationUnitsForEditorMessage");
static const int registerProjectPartsForEditorMessageType = QMetaType::type("ClangBackEnd::RegisterProjectPartsForEditorMessage"); static const int registerProjectPartsForEditorMessageType = QMetaType::type("ClangBackEnd::RegisterProjectPartsForEditorMessage");
static const int unregisterProjectPartsForEditorMessageType = QMetaType::type("ClangBackEnd::UnregisterProjectPartsForEditorMessage"); static const int unregisterProjectPartsForEditorMessageType = QMetaType::type("ClangBackEnd::UnregisterProjectPartsForEditorMessage");
@@ -62,6 +64,8 @@ void IpcServerInterface::dispatch(const QVariant &message)
end(); end();
else if (type == registerTranslationUnitsForEditorMessageType) else if (type == registerTranslationUnitsForEditorMessageType)
registerTranslationUnitsForEditor(message.value<RegisterTranslationUnitForEditorMessage>()); registerTranslationUnitsForEditor(message.value<RegisterTranslationUnitForEditorMessage>());
else if (type == updateTranslationUnitsForEditorMessageType)
updateTranslationUnitsForEditor(message.value<UpdateTranslationUnitsForEditorMessage>());
else if (type == unregisterTranslationUnitsForEditorMessageType) else if (type == unregisterTranslationUnitsForEditorMessageType)
unregisterTranslationUnitsForEditor(message.value<UnregisterTranslationUnitsForEditorMessage>()); unregisterTranslationUnitsForEditor(message.value<UnregisterTranslationUnitsForEditorMessage>());
else if (type == registerProjectPartsForEditorMessageType) else if (type == registerProjectPartsForEditorMessageType)

View File

@@ -46,6 +46,7 @@ public:
virtual void end() = 0; virtual void end() = 0;
virtual void registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message) = 0; virtual void registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message) = 0;
virtual void updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &message) = 0;
virtual void unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message) = 0; virtual void unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message) = 0;
virtual void registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &message) = 0; virtual void registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &message) = 0;
virtual void unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &message) = 0; virtual void unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &message) = 0;

View File

@@ -41,6 +41,7 @@
#include <registerunsavedfilesforeditormessage.h> #include <registerunsavedfilesforeditormessage.h>
#include <requestdiagnosticsmessage.h> #include <requestdiagnosticsmessage.h>
#include <unregisterunsavedfilesforeditormessage.h> #include <unregisterunsavedfilesforeditormessage.h>
#include <updatetranslationunitsforeditormessage.h>
#include <QLocalServer> #include <QLocalServer>
#include <QLocalSocket> #include <QLocalSocket>
@@ -78,6 +79,11 @@ void IpcServerProxy::registerTranslationUnitsForEditor(const RegisterTranslation
writeMessageBlock.write(QVariant::fromValue(message)); writeMessageBlock.write(QVariant::fromValue(message));
} }
void IpcServerProxy::updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &message)
{
writeMessageBlock.write(QVariant::fromValue(message));
}
void IpcServerProxy::unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message) void IpcServerProxy::unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message)
{ {
writeMessageBlock.write(QVariant::fromValue(message)); writeMessageBlock.write(QVariant::fromValue(message));

View File

@@ -57,6 +57,7 @@ public:
void end() override; void end() override;
void registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message) override; void registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message) override;
void updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &message) override;
void unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message) override; void unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message) override;
void registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &message) override; void registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &message) override;
void unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &message) override; void unregisterProjectPartsForEditor(const UnregisterProjectPartsForEditorMessage &message) override;

View File

@@ -0,0 +1,99 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "updatetranslationunitsforeditormessage.h"
#include "container_common.h"
#include <QDataStream>
#include <QDebug>
#include <ostream>
namespace ClangBackEnd {
UpdateTranslationUnitsForEditorMessage::UpdateTranslationUnitsForEditorMessage(const QVector<FileContainer> &fileContainers)
: fileContainers_(fileContainers)
{
}
const QVector<FileContainer> &UpdateTranslationUnitsForEditorMessage::fileContainers() const
{
return fileContainers_;
}
QDataStream &operator<<(QDataStream &out, const UpdateTranslationUnitsForEditorMessage &message)
{
out << message.fileContainers_;
return out;
}
QDataStream &operator>>(QDataStream &in, UpdateTranslationUnitsForEditorMessage &message)
{
in >> message.fileContainers_;
return in;
}
bool operator==(const UpdateTranslationUnitsForEditorMessage &first, const UpdateTranslationUnitsForEditorMessage &second)
{
return first.fileContainers_ == second.fileContainers_;
}
bool operator<(const UpdateTranslationUnitsForEditorMessage &first, const UpdateTranslationUnitsForEditorMessage &second)
{
return compareContainer(first.fileContainers_, second.fileContainers_);
}
QDebug operator<<(QDebug debug, const UpdateTranslationUnitsForEditorMessage &message)
{
debug.nospace() << "UpdateTranslationUnitsForEditorMessage(";
for (const FileContainer &fileContainer : message.fileContainers())
debug.nospace() << fileContainer<< ", ";
debug.nospace() << ")";
return debug;
}
void PrintTo(const UpdateTranslationUnitsForEditorMessage &message, ::std::ostream* os)
{
*os << "UpdateTranslationUnitsForEditorMessage(";
for (const FileContainer &fileContainer : message.fileContainers())
PrintTo(fileContainer, os);
*os << ")";
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,69 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://www.qt.io/licensing. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CLANGBACKEND_UPDATEFILEFOREDITOR_H
#define CLANGBACKEND_UPDATEFILEFOREDITOR_H
#include "filecontainer.h"
#include <QMetaType>
#include <QVector>
namespace ClangBackEnd {
class CMBIPC_EXPORT UpdateTranslationUnitsForEditorMessage
{
friend CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const UpdateTranslationUnitsForEditorMessage &message);
friend CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, UpdateTranslationUnitsForEditorMessage &message);
friend CMBIPC_EXPORT bool operator==(const UpdateTranslationUnitsForEditorMessage &first, const UpdateTranslationUnitsForEditorMessage &second);
friend CMBIPC_EXPORT bool operator<(const UpdateTranslationUnitsForEditorMessage &first, const UpdateTranslationUnitsForEditorMessage &second);
friend void PrintTo(const UpdateTranslationUnitsForEditorMessage &message, ::std::ostream* os);
public:
UpdateTranslationUnitsForEditorMessage() = default;
UpdateTranslationUnitsForEditorMessage(const QVector<FileContainer> &fileContainers);
const QVector<FileContainer> &fileContainers() const;
private:
QVector<FileContainer> fileContainers_;
};
CMBIPC_EXPORT QDataStream &operator<<(QDataStream &out, const UpdateTranslationUnitsForEditorMessage &message);
CMBIPC_EXPORT QDataStream &operator>>(QDataStream &in, UpdateTranslationUnitsForEditorMessage &message);
CMBIPC_EXPORT bool operator==(const UpdateTranslationUnitsForEditorMessage &first, const UpdateTranslationUnitsForEditorMessage &second);
CMBIPC_EXPORT bool operator<(const UpdateTranslationUnitsForEditorMessage &first, const UpdateTranslationUnitsForEditorMessage &second);
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const UpdateTranslationUnitsForEditorMessage &message);
void PrintTo(const UpdateTranslationUnitsForEditorMessage &message, ::std::ostream* os);
} // namespace ClangBackEnd
Q_DECLARE_METATYPE(ClangBackEnd::UpdateTranslationUnitsForEditorMessage)
#endif // CLANGBACKEND_UPDATEFILEFOREDITOR_H

View File

@@ -734,7 +734,7 @@ void Preprocessor::State::updateIncludeGuardState_helper(IncludeGuardStateHint h
#endif // DEBUG_INCLUDE_GUARD_TRACKING #endif // DEBUG_INCLUDE_GUARD_TRACKING
} }
const QString Preprocessor::configurationFileName = QLatin1String("<configuration>"); QString Preprocessor::configurationFileName() { return QStringLiteral("<configuration>"); }
Preprocessor::Preprocessor(Client *client, Environment *env) Preprocessor::Preprocessor(Client *client, Environment *env)
: m_client(client) : m_client(client)
@@ -1978,7 +1978,7 @@ void Preprocessor::handleIfDefDirective(bool checkUndefined, PPToken *tk)
// the macro is a feature constraint(e.g. QT_NO_XXX) // the macro is a feature constraint(e.g. QT_NO_XXX)
if (checkUndefined && macroName.startsWith("QT_NO_")) { if (checkUndefined && macroName.startsWith("QT_NO_")) {
if (macro->fileName() == configurationFileName) { if (macro->fileName() == configurationFileName()) {
// and it' defined in a pro file (e.g. DEFINES += QT_NO_QOBJECT) // and it' defined in a pro file (e.g. DEFINES += QT_NO_QOBJECT)
value = false; // take the branch value = false; // take the branch

View File

@@ -77,7 +77,7 @@ class CPLUSPLUS_EXPORT Preprocessor
typedef Internal::Value Value; typedef Internal::Value Value;
public: public:
static const QString configurationFileName; static QString configurationFileName();
public: public:
Preprocessor(Client *client, Environment *env); Preprocessor(Client *client, Environment *env);

View File

@@ -234,8 +234,6 @@ QtcLibrary {
"project/project.h", "project/project.h",
"project_controller/projectcontroller.cpp", "project_controller/projectcontroller.cpp",
"project_controller/projectcontroller.h", "project_controller/projectcontroller.h",
"serializer/diagramreferenceserializer.cpp",
"serializer/diagramreferenceserializer.h",
"serializer/diagramserializer.cpp", "serializer/diagramserializer.cpp",
"serializer/diagramserializer.h", "serializer/diagramserializer.h",
"serializer/infrastructureserializer.cpp", "serializer/infrastructureserializer.cpp",
@@ -314,6 +312,7 @@ QtcLibrary {
"inc/qark/impl/loadingrefmap.h", "inc/qark/impl/loadingrefmap.h",
"inc/qark/impl/objectid.h", "inc/qark/impl/objectid.h",
"inc/qark/impl/savingrefmap.h", "inc/qark/impl/savingrefmap.h",
"inc/qark/parameters.h",
"inc/qark/qxmlinarchive.h", "inc/qark/qxmlinarchive.h",
"inc/qark/qxmloutarchive.h", "inc/qark/qxmloutarchive.h",
"inc/qark/reference.h", "inc/qark/reference.h",
@@ -321,6 +320,7 @@ QtcLibrary {
"inc/qark/serialize_basic.h", "inc/qark/serialize_basic.h",
"inc/qark/serialize_container.h", "inc/qark/serialize_container.h",
"inc/qark/serialize_enum.h", "inc/qark/serialize_enum.h",
"inc/qark/serialize_pointer.h",
"inc/qark/tag.h", "inc/qark/tag.h",
"inc/qark/typeregistry.h", "inc/qark/typeregistry.h",
"src/flag.cpp", "src/flag.cpp",

View File

@@ -481,7 +481,7 @@ bool operator <(const ImportKey &i1, const ImportKey &i2)
return i1.compare(i2) < 0; return i1.compare(i2) < 0;
} }
const QString Export::LibraryTypeName = QLatin1String("%Library%"); QString Export::libraryTypeName() { return QStringLiteral("%Library%"); }
Export::Export() Export::Export()
: intrinsic(false) : intrinsic(false)

View File

@@ -131,10 +131,10 @@ bool operator <(const ImportKey &i1, const ImportKey &i2);
class QMLJS_EXPORT Export class QMLJS_EXPORT Export
{ {
public: public:
static const QString LibraryTypeName; static QString libraryTypeName();
Export(); Export();
Export(ImportKey exportName, QString pathRequired, bool intrinsic = false, Export(ImportKey exportName, QString pathRequired, bool intrinsic = false,
const QString &typeName = LibraryTypeName); const QString &typeName = libraryTypeName());
ImportKey exportName; ImportKey exportName;
QString pathRequired; QString pathRequired;
QString typeName; QString typeName;
@@ -211,9 +211,9 @@ public:
void removeCoreImport(const QString &importId); void removeCoreImport(const QString &importId);
void addExport(const QString &importId, const ImportKey &importKey, void addExport(const QString &importId, const ImportKey &importKey,
const QString &requiredPath, const QString &typeName = Export::LibraryTypeName); const QString &requiredPath, const QString &typeName = Export::libraryTypeName());
void removeExport(const QString &importId, const ImportKey &importKey, void removeExport(const QString &importId, const ImportKey &importKey,
const QString &requiredPath, const QString &typeName = Export::LibraryTypeName); const QString &requiredPath, const QString &typeName = Export::libraryTypeName());
void iterateOnCoreImports(const ViewerContext &vContext, void iterateOnCoreImports(const ViewerContext &vContext,
std::function<bool(const CoreImport &)> const &iterF) const; std::function<bool(const CoreImport &)> const &iterF) const;

View File

@@ -273,7 +273,7 @@ void LinkPrivate::populateImportedTypes(Imports *imports, Document::Ptr doc)
imports->setImportFailed(); imports->setImportFailed();
if (info.ast()) { if (info.ast()) {
error(doc, info.ast()->fileNameToken, error(doc, info.ast()->fileNameToken,
Link::tr("file or directory not found")); Link::tr("File or directory not found."));
} }
break; break;
default: default:
@@ -436,11 +436,11 @@ Import LinkPrivate::importNonFile(Document::Ptr doc, const ImportInfo &importInf
error(doc, locationFromRange(importInfo.ast()->firstSourceLocation(), error(doc, locationFromRange(importInfo.ast()->firstSourceLocation(),
importInfo.ast()->lastSourceLocation()), importInfo.ast()->lastSourceLocation()),
Link::tr( Link::tr(
"QML module not found\n\n" "QML module not found.\n\n"
"Import paths:\n" "Import paths:\n"
"%1\n\n" "%1\n\n"
"For qmake projects, use the QML_IMPORT_PATH variable to add import paths.\n" "For qmake projects, use the QML_IMPORT_PATH variable to add import paths.\n"
"For qbs projects, declare and set a qmlImportPaths property in your product " "For Qbs projects, declare and set a qmlImportPaths property in your product "
"to add import paths.\n" "to add import paths.\n"
"For qmlproject projects, use the importPaths property to add import paths.").arg( "For qmlproject projects, use the importPaths property to add import paths.").arg(
importPaths.join(QLatin1Char('\n')))); importPaths.join(QLatin1Char('\n'))));

View File

@@ -49,17 +49,17 @@ std::wstring StackFrame::fileName() const
void StackFrame::formatGDBMI(std::ostream &str, unsigned level) const void StackFrame::formatGDBMI(std::ostream &str, unsigned level) const
{ {
str << "frame={level=\"" << level << "\",addr=\"0x" str << "frame={level=\"" << level << "\",address=\"0x"
<< std::hex << address << std::dec << '"'; << std::hex << address << std::dec << '"';
if (!function.empty()) { if (!function.empty()) {
// Split into module/function // Split into module/function
const std::wstring::size_type exclPos = function.find('!'); const std::wstring::size_type exclPos = function.find('!');
if (exclPos == std::wstring::npos) { if (exclPos == std::wstring::npos) {
str << ",func=\"" << gdbmiWStringFormat(function) << '"'; str << ",function=\"" << gdbmiWStringFormat(function) << '"';
} else { } else {
const std::wstring module = function.substr(0, exclPos); const std::wstring module = function.substr(0, exclPos);
const std::wstring fn = function.substr(exclPos + 1, function.size() - exclPos - 1); const std::wstring fn = function.substr(exclPos + 1, function.size() - exclPos - 1);
str << ",func=\"" << gdbmiWStringFormat(fn) str << ",function=\"" << gdbmiWStringFormat(fn)
<< "\",from=\"" << gdbmiWStringFormat(module) << '"'; << "\",from=\"" << gdbmiWStringFormat(module) << '"';
} }
} }

View File

@@ -263,7 +263,6 @@ struct TransformImpl {
static C call(const SC &container, F function) static C call(const SC &container, F function)
{ {
C result; C result;
result.reserve(container.size());
std::transform(container.begin(), container.end(), std::transform(container.begin(), container.end(),
inserter(result), inserter(result),
function); function);
@@ -337,6 +336,29 @@ auto transform(const SC &container, R (S::*p)() const)
>::call(container, p); >::call(container, p);
} }
//////////////////
// filtered
/////////////////
template<typename C, typename F>
Q_REQUIRED_RESULT
C filtered(const C &container, F predicate)
{
C out;
std::copy_if(container.begin(), container.end(),
inserter(out), predicate);
return out;
}
template<typename C, typename R, typename S>
Q_REQUIRED_RESULT
C filtered(const C &container, R (S::*predicate)() const)
{
C out;
std::copy_if(container.begin(), container.end(),
inserter(out), std::mem_fn(predicate));
return out;
}
////////////////// //////////////////
// sort // sort
///////////////// /////////////////

View File

@@ -92,46 +92,42 @@ public:
virtual bool eventFilter(QObject *obj, QEvent *event); virtual bool eventFilter(QObject *obj, QEvent *event);
FancyLineEdit *m_lineEdit; FancyLineEdit *m_lineEdit;
IconButton *m_iconbutton[2];
HistoryCompleter *m_historyCompleter = 0;
FancyLineEdit::ValidationFunction m_validationFunction = &FancyLineEdit::validateWithValidator;
QString m_oldText; QString m_oldText;
QPixmap m_pixmap[2]; QPixmap m_pixmap[2];
QMenu *m_menu[2]; QMenu *m_menu[2];
FancyLineEdit::State m_state = FancyLineEdit::Invalid;
bool m_menuTabFocusTrigger[2]; bool m_menuTabFocusTrigger[2];
IconButton *m_iconbutton[2];
bool m_iconEnabled[2]; bool m_iconEnabled[2];
HistoryCompleter *m_historyCompleter; bool m_isFiltering = false;
FancyLineEdit::ValidationFunction m_validationFunction; bool m_firstChange = false;
bool m_isFiltering;
QString m_lastFilterText; QString m_lastFilterText;
const QColor m_okTextColor; QColor m_okTextColor;
QColor m_errorTextColor; QColor m_errorTextColor = Qt::red;
FancyLineEdit::State m_state;
QString m_errorMessage; QString m_errorMessage;
QString m_initialText; QString m_initialText;
bool m_firstChange;
}; };
FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) : FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) :
QObject(parent), QObject(parent),
m_lineEdit(parent), m_lineEdit(parent)
m_historyCompleter(0),
m_validationFunction(FancyLineEdit::defaultValidationFunction()),
m_isFiltering(false),
m_okTextColor(FancyLineEdit::textColor(parent)),
m_errorTextColor(Qt::red),
m_state(FancyLineEdit::Invalid),
m_firstChange(true)
{ {
m_okTextColor = parent->palette().color(QPalette::Active, QPalette::Text);
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
m_menu[i] = 0;
m_menuTabFocusTrigger[i] = false;
m_iconbutton[i] = new IconButton(parent); m_iconbutton[i] = new IconButton(parent);
m_iconbutton[i]->installEventFilter(this); m_iconbutton[i]->installEventFilter(this);
m_iconbutton[i]->hide(); m_iconbutton[i]->hide();
m_iconbutton[i]->setAutoHide(false); m_iconbutton[i]->setAutoHide(false);
m_menu[i] = 0;
m_menuTabFocusTrigger[i] = false;
m_iconEnabled[i] = false; m_iconEnabled[i] = false;
} }
} }
@@ -171,7 +167,7 @@ FancyLineEdit::FancyLineEdit(QWidget *parent) :
connect(d->m_iconbutton[Left], &QAbstractButton::clicked, this, &FancyLineEdit::iconClicked); connect(d->m_iconbutton[Left], &QAbstractButton::clicked, this, &FancyLineEdit::iconClicked);
connect(d->m_iconbutton[Right], &QAbstractButton::clicked, this, &FancyLineEdit::iconClicked); connect(d->m_iconbutton[Right], &QAbstractButton::clicked, this, &FancyLineEdit::iconClicked);
connect(this, &QLineEdit::textChanged, this, &FancyLineEdit::onTextChanged); connect(this, &QLineEdit::textChanged, this, &FancyLineEdit::validate);
} }
FancyLineEdit::~FancyLineEdit() FancyLineEdit::~FancyLineEdit()
@@ -406,18 +402,18 @@ QColor FancyLineEdit::errorColor() const
void FancyLineEdit::setErrorColor(const QColor &c) void FancyLineEdit::setErrorColor(const QColor &c)
{ {
d->m_errorTextColor = c; d->m_errorTextColor = c;
validate();
} }
QColor FancyLineEdit::textColor(const QWidget *w) QColor FancyLineEdit::okColor() const
{ {
return w->palette().color(QPalette::Active, QPalette::Text); return d->m_okTextColor;
} }
void FancyLineEdit::setTextColor(QWidget *w, const QColor &c) void FancyLineEdit::setOkColor(const QColor &c)
{ {
QPalette palette = w->palette(); d->m_okTextColor = c;
palette.setColor(QPalette::Active, QPalette::Text, c); validate();
w->setPalette(palette);
} }
void FancyLineEdit::setValidationFunction(const FancyLineEdit::ValidationFunction &fn) void FancyLineEdit::setValidationFunction(const FancyLineEdit::ValidationFunction &fn)
@@ -456,8 +452,10 @@ QString FancyLineEdit::errorMessage() const
return d->m_errorMessage; return d->m_errorMessage;
} }
void FancyLineEdit::onTextChanged(const QString &t) void FancyLineEdit::validate()
{ {
const QString t = text();
if (d->m_isFiltering){ if (d->m_isFiltering){
if (t != d->m_lastFilterText) { if (t != d->m_lastFilterText) {
d->m_lastFilterText = t; d->m_lastFilterText = t;
@@ -478,7 +476,11 @@ void FancyLineEdit::onTextChanged(const QString &t)
const bool validHasChanged = (d->m_state == Valid) != (newState == Valid); const bool validHasChanged = (d->m_state == Valid) != (newState == Valid);
d->m_state = newState; d->m_state = newState;
d->m_firstChange = false; d->m_firstChange = false;
setTextColor(this, newState == Invalid ? d->m_errorTextColor : d->m_okTextColor);
QPalette p = palette();
p.setColor(QPalette::Active, QPalette::Text, newState == Invalid ? d->m_errorTextColor : d->m_okTextColor);
setPalette(p);
if (validHasChanged) if (validHasChanged)
emit validChanged(newState == Valid); emit validChanged(newState == Valid);
} }
@@ -503,17 +505,11 @@ void FancyLineEdit::onTextChanged(const QString &t)
handleChanged(t); handleChanged(t);
} }
void FancyLineEdit::triggerChanged()
{
onTextChanged(text());
}
QString FancyLineEdit::fixInputString(const QString &string) QString FancyLineEdit::fixInputString(const QString &string)
{ {
return string; return string;
} }
// //
// IconButton - helper class to represent a clickable icon // IconButton - helper class to represent a clickable icon
// //

View File

@@ -84,6 +84,7 @@ class QTCREATOR_UTILS_EXPORT FancyLineEdit : public CompletingLineEdit
// Validation. // Validation.
Q_PROPERTY(QString initialText READ initialText WRITE setInitialText DESIGNABLE true) Q_PROPERTY(QString initialText READ initialText WRITE setInitialText DESIGNABLE true)
Q_PROPERTY(QColor errorColor READ errorColor WRITE setErrorColor DESIGNABLE true) Q_PROPERTY(QColor errorColor READ errorColor WRITE setErrorColor DESIGNABLE true)
Q_PROPERTY(QColor okColor READ okColor WRITE setOkColor DESIGNABLE true)
public: public:
enum Side {Left = 0, Right = 1}; enum Side {Left = 0, Right = 1};
@@ -141,18 +142,17 @@ public:
void setInitialText(const QString &); void setInitialText(const QString &);
QColor errorColor() const; QColor errorColor() const;
void setErrorColor(const QColor &); void setErrorColor(const QColor &c);
// Trigger an update (after changing settings) QColor okColor() const;
void triggerChanged(); void setOkColor(const QColor &c);
static QColor textColor(const QWidget *w);
static void setTextColor(QWidget *w, const QColor &c);
void setValidationFunction(const ValidationFunction &fn); void setValidationFunction(const ValidationFunction &fn);
static ValidationFunction defaultValidationFunction(); static ValidationFunction defaultValidationFunction();
void validate();
void onEditingFinished();
protected slots: protected:
// Custom behaviour can be added here. // Custom behaviour can be added here.
virtual void handleChanged(const QString &) {} virtual void handleChanged(const QString &) {}
@@ -166,17 +166,14 @@ signals:
void validChanged(bool validState); void validChanged(bool validState);
void validReturnPressed(); void validReturnPressed();
private slots:
void iconClicked();
void onTextChanged(const QString &);
void onEditingFinished();
protected: protected:
void resizeEvent(QResizeEvent *e); void resizeEvent(QResizeEvent *e);
virtual QString fixInputString(const QString &string); virtual QString fixInputString(const QString &string);
private: private:
void iconClicked();
static bool validateWithValidator(FancyLineEdit *edit, QString *errorMessage); static bool validateWithValidator(FancyLineEdit *edit, QString *errorMessage);
// Unimplemented, to force the user to make a decision on // Unimplemented, to force the user to make a decision on
// whether to use setHistoryCompleter() or setSpecialCompleter(). // whether to use setHistoryCompleter() or setSpecialCompleter().

View File

@@ -137,28 +137,28 @@ JsonValue *JsonValue::build(const QVariant &variant, JsonMemoryPool *pool)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
const QString JsonSchema::kType(QLatin1String("type")); QString JsonSchema::kType() { return QStringLiteral("type"); }
const QString JsonSchema::kProperties(QLatin1String("properties")); QString JsonSchema::kProperties() { return QStringLiteral("properties"); }
const QString JsonSchema::kPatternProperties(QLatin1String("patternProperties")); QString JsonSchema::kPatternProperties() { return QStringLiteral("patternProperties"); }
const QString JsonSchema::kAdditionalProperties(QLatin1String("additionalProperties")); QString JsonSchema::kAdditionalProperties() { return QStringLiteral("additionalProperties"); }
const QString JsonSchema::kItems(QLatin1String("items")); QString JsonSchema::kItems() { return QStringLiteral("items"); }
const QString JsonSchema::kAdditionalItems(QLatin1String("additionalItems")); QString JsonSchema::kAdditionalItems() { return QStringLiteral("additionalItems"); }
const QString JsonSchema::kRequired(QLatin1String("required")); QString JsonSchema::kRequired() { return QStringLiteral("required"); }
const QString JsonSchema::kDependencies(QLatin1String("dependencies")); QString JsonSchema::kDependencies() { return QStringLiteral("dependencies"); }
const QString JsonSchema::kMinimum(QLatin1String("minimum")); QString JsonSchema::kMinimum() { return QStringLiteral("minimum"); }
const QString JsonSchema::kMaximum(QLatin1String("maximum")); QString JsonSchema::kMaximum() { return QStringLiteral("maximum"); }
const QString JsonSchema::kExclusiveMinimum(QLatin1String("exclusiveMinimum")); QString JsonSchema::kExclusiveMinimum() { return QStringLiteral("exclusiveMinimum"); }
const QString JsonSchema::kExclusiveMaximum(QLatin1String("exclusiveMaximum")); QString JsonSchema::kExclusiveMaximum() { return QStringLiteral("exclusiveMaximum"); }
const QString JsonSchema::kMinItems(QLatin1String("minItems")); QString JsonSchema::kMinItems() { return QStringLiteral("minItems"); }
const QString JsonSchema::kMaxItems(QLatin1String("maxItems")); QString JsonSchema::kMaxItems() { return QStringLiteral("maxItems"); }
const QString JsonSchema::kUniqueItems(QLatin1String("uniqueItems")); QString JsonSchema::kUniqueItems() { return QStringLiteral("uniqueItems"); }
const QString JsonSchema::kPattern(QLatin1String("pattern")); QString JsonSchema::kPattern() { return QStringLiteral("pattern"); }
const QString JsonSchema::kMinLength(QLatin1String("minLength")); QString JsonSchema::kMinLength() { return QStringLiteral("minLength"); }
const QString JsonSchema::kMaxLength(QLatin1String("maxLength")); QString JsonSchema::kMaxLength() { return QStringLiteral("maxLength"); }
const QString JsonSchema::kTitle(QLatin1String("title")); QString JsonSchema::kTitle() { return QStringLiteral("title"); }
const QString JsonSchema::kDescription(QLatin1String("description")); QString JsonSchema::kDescription() { return QStringLiteral("description"); }
const QString JsonSchema::kExtends(QLatin1String("extends")); QString JsonSchema::kExtends() { return QStringLiteral("extends"); }
const QString JsonSchema::kRef(QLatin1String("$ref")); QString JsonSchema::kRef() { return QStringLiteral("$ref"); }
JsonSchema::JsonSchema(JsonObjectValue *rootObject, const JsonSchemaManager *manager) JsonSchema::JsonSchema(JsonObjectValue *rootObject, const JsonSchemaManager *manager)
: m_manager(manager) : m_manager(manager)
@@ -169,11 +169,11 @@ JsonSchema::JsonSchema(JsonObjectValue *rootObject, const JsonSchemaManager *man
bool JsonSchema::isTypeConstrained() const bool JsonSchema::isTypeConstrained() const
{ {
// Simple types // Simple types
if (JsonStringValue *sv = getStringValue(kType, currentValue())) if (JsonStringValue *sv = getStringValue(kType(), currentValue()))
return isCheckableType(sv->value()); return isCheckableType(sv->value());
// Union types // Union types
if (JsonArrayValue *av = getArrayValue(kType, currentValue())) { if (JsonArrayValue *av = getArrayValue(kType(), currentValue())) {
QTC_ASSERT(currentIndex() != -1, return false); QTC_ASSERT(currentIndex() != -1, return false);
QTC_ASSERT(av->elements().at(currentIndex())->kind() == JsonValue::String, return false); QTC_ASSERT(av->elements().at(currentIndex())->kind() == JsonValue::String, return false);
JsonStringValue *sv = av->elements().at(currentIndex())->toString(); JsonStringValue *sv = av->elements().at(currentIndex())->toString();
@@ -186,11 +186,11 @@ bool JsonSchema::isTypeConstrained() const
bool JsonSchema::acceptsType(const QString &type) const bool JsonSchema::acceptsType(const QString &type) const
{ {
// Simple types // Simple types
if (JsonStringValue *sv = getStringValue(kType, currentValue())) if (JsonStringValue *sv = getStringValue(kType(), currentValue()))
return typeMatches(sv->value(), type); return typeMatches(sv->value(), type);
// Union types // Union types
if (JsonArrayValue *av = getArrayValue(kType, currentValue())) { if (JsonArrayValue *av = getArrayValue(kType(), currentValue())) {
QTC_ASSERT(currentIndex() != -1, return false); QTC_ASSERT(currentIndex() != -1, return false);
QTC_ASSERT(av->elements().at(currentIndex())->kind() == JsonValue::String, return false); QTC_ASSERT(av->elements().at(currentIndex())->kind() == JsonValue::String, return false);
JsonStringValue *sv = av->elements().at(currentIndex())->toString(); JsonStringValue *sv = av->elements().at(currentIndex())->toString();
@@ -204,13 +204,13 @@ QStringList JsonSchema::validTypes(JsonObjectValue *v)
{ {
QStringList all; QStringList all;
if (JsonStringValue *sv = getStringValue(kType, v)) if (JsonStringValue *sv = getStringValue(kType(), v))
all.append(sv->value()); all.append(sv->value());
if (JsonObjectValue *ov = getObjectValue(kType, v)) if (JsonObjectValue *ov = getObjectValue(kType(), v))
return validTypes(ov); return validTypes(ov);
if (JsonArrayValue *av = getArrayValue(kType, v)) { if (JsonArrayValue *av = getArrayValue(kType(), v)) {
foreach (JsonValue *v, av->elements()) { foreach (JsonValue *v, av->elements()) {
if (JsonStringValue *sv = v->toString()) if (JsonStringValue *sv = v->toString())
all.append(sv->value()); all.append(sv->value());
@@ -252,14 +252,14 @@ QStringList JsonSchema::validTypes() const
bool JsonSchema::hasTypeSchema() const bool JsonSchema::hasTypeSchema() const
{ {
return getObjectValue(kType, currentValue()); return getObjectValue(kType(), currentValue());
} }
void JsonSchema::enterNestedTypeSchema() void JsonSchema::enterNestedTypeSchema()
{ {
QTC_ASSERT(hasTypeSchema(), return); QTC_ASSERT(hasTypeSchema(), return);
enter(getObjectValue(kType, currentValue())); enter(getObjectValue(kType(), currentValue()));
} }
QStringList JsonSchema::properties(JsonObjectValue *v) const QStringList JsonSchema::properties(JsonObjectValue *v) const
@@ -268,7 +268,7 @@ QStringList JsonSchema::properties(JsonObjectValue *v) const
QStringList all; QStringList all;
if (JsonObjectValue *ov = getObjectValue(kProperties, v)) { if (JsonObjectValue *ov = getObjectValue(kProperties(), v)) {
const MemberConstIterator cend = ov->members().constEnd(); const MemberConstIterator cend = ov->members().constEnd();
for (MemberConstIterator it = ov->members().constBegin(); it != cend; ++it) for (MemberConstIterator it = ov->members().constBegin(); it != cend; ++it)
if (hasPropertySchema(it.key())) if (hasPropertySchema(it.key()))
@@ -291,7 +291,7 @@ QStringList JsonSchema::properties() const
JsonObjectValue *JsonSchema::propertySchema(const QString &property, JsonObjectValue *JsonSchema::propertySchema(const QString &property,
JsonObjectValue *v) const JsonObjectValue *v) const
{ {
if (JsonObjectValue *ov = getObjectValue(kProperties, v)) { if (JsonObjectValue *ov = getObjectValue(kProperties(), v)) {
JsonValue *member = ov->member(property); JsonValue *member = ov->member(property);
if (member && member->kind() == JsonValue::Object) if (member && member->kind() == JsonValue::Object)
return member->toObject(); return member->toObject();
@@ -329,14 +329,14 @@ bool JsonSchema::hasItemSchema() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false);
return getObjectValue(kItems, currentValue()); return getObjectValue(kItems(), currentValue());
} }
void JsonSchema::enterNestedItemSchema() void JsonSchema::enterNestedItemSchema()
{ {
QTC_ASSERT(hasItemSchema(), return); QTC_ASSERT(hasItemSchema(), return);
enter(getObjectValue(kItems, currentValue())); enter(getObjectValue(kItems(), currentValue()));
} }
/*! /*!
@@ -350,14 +350,14 @@ bool JsonSchema::hasItemArraySchema() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false);
return getArrayValue(kItems, currentValue()); return getArrayValue(kItems(), currentValue());
} }
int JsonSchema::itemArraySchemaSize() const int JsonSchema::itemArraySchemaSize() const
{ {
QTC_ASSERT(hasItemArraySchema(), return false); QTC_ASSERT(hasItemArraySchema(), return false);
return getArrayValue(kItems, currentValue())->size(); return getArrayValue(kItems(), currentValue())->size();
} }
/*! /*!
@@ -377,7 +377,7 @@ bool JsonSchema::maybeEnterNestedArraySchema(int index)
QTC_ASSERT(itemArraySchemaSize(), return false); QTC_ASSERT(itemArraySchemaSize(), return false);
QTC_ASSERT(index >= 0 && index < itemArraySchemaSize(), return false); QTC_ASSERT(index >= 0 && index < itemArraySchemaSize(), return false);
JsonValue *v = getArrayValue(kItems, currentValue())->elements().at(index); JsonValue *v = getArrayValue(kItems(), currentValue())->elements().at(index);
return maybeEnter(v, Array, index); return maybeEnter(v, Array, index);
} }
@@ -391,12 +391,12 @@ bool JsonSchema::maybeEnterNestedArraySchema(int index)
*/ */
bool JsonSchema::hasUnionSchema() const bool JsonSchema::hasUnionSchema() const
{ {
return getArrayValue(kType, currentValue()); return getArrayValue(kType(), currentValue());
} }
int JsonSchema::unionSchemaSize() const int JsonSchema::unionSchemaSize() const
{ {
return getArrayValue(kType, currentValue())->size(); return getArrayValue(kType(), currentValue())->size();
} }
/*! /*!
@@ -416,7 +416,7 @@ bool JsonSchema::maybeEnterNestedUnionSchema(int index)
QTC_ASSERT(unionSchemaSize(), return false); QTC_ASSERT(unionSchemaSize(), return false);
QTC_ASSERT(index >= 0 && index < unionSchemaSize(), return false); QTC_ASSERT(index >= 0 && index < unionSchemaSize(), return false);
JsonValue *v = getArrayValue(kType, currentValue())->elements().at(index); JsonValue *v = getArrayValue(kType(), currentValue())->elements().at(index);
return maybeEnter(v, Union, index); return maybeEnter(v, Union, index);
} }
@@ -430,7 +430,7 @@ void JsonSchema::leaveNestedSchema()
bool JsonSchema::required() const bool JsonSchema::required() const
{ {
if (JsonBooleanValue *bv = getBooleanValue(kRequired, currentValue())) if (JsonBooleanValue *bv = getBooleanValue(kRequired(), currentValue()))
return bv->value(); return bv->value();
return false; return false;
@@ -440,21 +440,21 @@ bool JsonSchema::hasMinimum() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false);
return getDoubleValue(kMinimum, currentValue()); return getDoubleValue(kMinimum(), currentValue());
} }
double JsonSchema::minimum() const double JsonSchema::minimum() const
{ {
QTC_ASSERT(hasMinimum(), return 0); QTC_ASSERT(hasMinimum(), return 0);
return getDoubleValue(kMinimum, currentValue())->value(); return getDoubleValue(kMinimum(), currentValue())->value();
} }
bool JsonSchema::hasExclusiveMinimum() bool JsonSchema::hasExclusiveMinimum()
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false);
if (JsonBooleanValue *bv = getBooleanValue(kExclusiveMinimum, currentValue())) if (JsonBooleanValue *bv = getBooleanValue(kExclusiveMinimum(), currentValue()))
return bv->value(); return bv->value();
return false; return false;
@@ -464,21 +464,21 @@ bool JsonSchema::hasMaximum() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false);
return getDoubleValue(kMaximum, currentValue()); return getDoubleValue(kMaximum(), currentValue());
} }
double JsonSchema::maximum() const double JsonSchema::maximum() const
{ {
QTC_ASSERT(hasMaximum(), return 0); QTC_ASSERT(hasMaximum(), return 0);
return getDoubleValue(kMaximum, currentValue())->value(); return getDoubleValue(kMaximum(), currentValue())->value();
} }
bool JsonSchema::hasExclusiveMaximum() bool JsonSchema::hasExclusiveMaximum()
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false);
if (JsonBooleanValue *bv = getBooleanValue(kExclusiveMaximum, currentValue())) if (JsonBooleanValue *bv = getBooleanValue(kExclusiveMaximum(), currentValue()))
return bv->value(); return bv->value();
return false; return false;
@@ -488,7 +488,7 @@ QString JsonSchema::pattern() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return QString()); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return QString());
if (JsonStringValue *sv = getStringValue(kPattern, currentValue())) if (JsonStringValue *sv = getStringValue(kPattern(), currentValue()))
return sv->value(); return sv->value();
return QString(); return QString();
@@ -498,7 +498,7 @@ int JsonSchema::minimumLength() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return -1); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return -1);
if (JsonDoubleValue *dv = getDoubleValue(kMinLength, currentValue())) if (JsonDoubleValue *dv = getDoubleValue(kMinLength(), currentValue()))
return dv->value(); return dv->value();
return -1; return -1;
@@ -508,7 +508,7 @@ int JsonSchema::maximumLength() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return -1); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::String)), return -1);
if (JsonDoubleValue *dv = getDoubleValue(kMaxLength, currentValue())) if (JsonDoubleValue *dv = getDoubleValue(kMaxLength(), currentValue()))
return dv->value(); return dv->value();
return -1; return -1;
@@ -518,7 +518,7 @@ bool JsonSchema::hasAdditionalItems() const
{ {
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false); QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false);
return currentValue()->member(kAdditionalItems); return currentValue()->member(kAdditionalItems());
} }
bool JsonSchema::maybeSchemaName(const QString &s) bool JsonSchema::maybeSchemaName(const QString &s)
@@ -600,7 +600,7 @@ void JsonSchema::leave()
JsonObjectValue *JsonSchema::resolveReference(JsonObjectValue *ov) const JsonObjectValue *JsonSchema::resolveReference(JsonObjectValue *ov) const
{ {
if (JsonStringValue *sv = getStringValue(kRef, ov)) { if (JsonStringValue *sv = getStringValue(kRef(), ov)) {
JsonSchema *referenced = m_manager->schemaByName(sv->value()); JsonSchema *referenced = m_manager->schemaByName(sv->value());
if (referenced) if (referenced)
return referenced->rootValue(); return referenced->rootValue();
@@ -611,7 +611,7 @@ JsonObjectValue *JsonSchema::resolveReference(JsonObjectValue *ov) const
JsonObjectValue *JsonSchema::resolveBase(JsonObjectValue *ov) const JsonObjectValue *JsonSchema::resolveBase(JsonObjectValue *ov) const
{ {
if (JsonValue *v = ov->member(kExtends)) { if (JsonValue *v = ov->member(kExtends())) {
if (v->kind() == JsonValue::String) { if (v->kind() == JsonValue::String) {
JsonSchema *schema = m_manager->schemaByName(v->toString()->value()); JsonSchema *schema = m_manager->schemaByName(v->toString()->value());
if (schema) if (schema)

View File

@@ -355,28 +355,28 @@ private:
static bool maybeSchemaName(const QString &s); static bool maybeSchemaName(const QString &s);
static const QString kType; static QString kType();
static const QString kProperties; static QString kProperties();
static const QString kPatternProperties; static QString kPatternProperties();
static const QString kAdditionalProperties; static QString kAdditionalProperties();
static const QString kItems; static QString kItems();
static const QString kAdditionalItems; static QString kAdditionalItems();
static const QString kRequired; static QString kRequired();
static const QString kDependencies; static QString kDependencies();
static const QString kMinimum; static QString kMinimum();
static const QString kMaximum; static QString kMaximum();
static const QString kExclusiveMinimum; static QString kExclusiveMinimum();
static const QString kExclusiveMaximum; static QString kExclusiveMaximum();
static const QString kMinItems; static QString kMinItems();
static const QString kMaxItems; static QString kMaxItems();
static const QString kUniqueItems; static QString kUniqueItems();
static const QString kPattern; static QString kPattern();
static const QString kMinLength; static QString kMinLength();
static const QString kMaxLength; static QString kMaxLength();
static const QString kTitle; static QString kTitle();
static const QString kDescription; static QString kDescription();
static const QString kExtends; static QString kExtends();
static const QString kRef; static QString kRef();
struct Context struct Context
{ {

View File

@@ -533,11 +533,6 @@ bool NewClassWidget::isValid(QString *error) const
return true; return true;
} }
void NewClassWidget::triggerUpdateFileNames()
{
d->m_ui.classLineEdit->triggerChanged();
}
void NewClassWidget::slotUpdateFileNames(const QString &baseName) void NewClassWidget::slotUpdateFileNames(const QString &baseName)
{ {
if (debugNewClassWidget) if (debugNewClassWidget)

View File

@@ -155,10 +155,6 @@ public slots:
*/ */
void suggestClassNameFromBase(); void suggestClassNameFromBase();
public slots:
/** Trigger an update (after changing settings) */
void triggerUpdateFileNames();
private slots: private slots:
void slotUpdateFileNames(const QString &t); void slotUpdateFileNames(const QString &t);
void slotValidChanged(); void slotValidChanged();

View File

@@ -336,6 +336,16 @@ void PathChooser::setFileName(const FileName &fn)
d->m_lineEdit->setText(fn.toUserOutput()); d->m_lineEdit->setText(fn.toUserOutput());
} }
void PathChooser::setErrorColor(const QColor &errorColor)
{
d->m_lineEdit->setErrorColor(errorColor);
}
void PathChooser::setOkColor(const QColor &okColor)
{
d->m_lineEdit->setOkColor(okColor);
}
bool PathChooser::isReadOnly() const bool PathChooser::isReadOnly() const
{ {
return d->m_lineEdit->isReadOnly(); return d->m_lineEdit->isReadOnly();
@@ -453,7 +463,7 @@ QString PathChooser::errorMessage() const
void PathChooser::triggerChanged() void PathChooser::triggerChanged()
{ {
d->m_lineEdit->triggerChanged(); d->m_lineEdit->validate();
} }
void PathChooser::setAboutToShowContextMenuHandler(PathChooser::AboutToShowContextMenuHandler handler) void PathChooser::setAboutToShowContextMenuHandler(PathChooser::AboutToShowContextMenuHandler handler)
@@ -461,6 +471,16 @@ void PathChooser::setAboutToShowContextMenuHandler(PathChooser::AboutToShowConte
s_aboutToShowContextMenuHandler = handler; s_aboutToShowContextMenuHandler = handler;
} }
QColor PathChooser::errorColor() const
{
return d->m_lineEdit->errorColor();
}
QColor PathChooser::okColor() const
{
return d->m_lineEdit->okColor();
}
FancyLineEdit::ValidationFunction PathChooser::defaultValidationFunction() const FancyLineEdit::ValidationFunction PathChooser::defaultValidationFunction() const
{ {
return std::bind(&PathChooser::validatePath, this, std::placeholders::_1, std::placeholders::_2); return std::bind(&PathChooser::validatePath, this, std::placeholders::_1, std::placeholders::_2);
@@ -616,7 +636,7 @@ void PathChooser::setExpectedKind(Kind expected)
if (d->m_acceptingKind == expected) if (d->m_acceptingKind == expected)
return; return;
d->m_acceptingKind = expected; d->m_acceptingKind = expected;
d->m_lineEdit->triggerChanged(); d->m_lineEdit->validate();
} }
PathChooser::Kind PathChooser::expectedKind() const PathChooser::Kind PathChooser::expectedKind() const

View File

@@ -62,6 +62,8 @@ class QTCREATOR_UTILS_EXPORT PathChooser : public QWidget
// Designer does not know this type, so force designable to false: // Designer does not know this type, so force designable to false:
Q_PROPERTY(Utils::FileName fileName READ fileName WRITE setFileName DESIGNABLE false) Q_PROPERTY(Utils::FileName fileName READ fileName WRITE setFileName DESIGNABLE false)
Q_PROPERTY(Utils::FileName baseFileName READ baseFileName WRITE setBaseFileName DESIGNABLE false) Q_PROPERTY(Utils::FileName baseFileName READ baseFileName WRITE setBaseFileName DESIGNABLE false)
Q_PROPERTY(QColor errorColor READ errorColor WRITE setErrorColor DESIGNABLE true)
Q_PROPERTY(QColor okColor READ okColor WRITE setOkColor DESIGNABLE true)
public: public:
static QString browseButtonLabel(); static QString browseButtonLabel();
@@ -145,6 +147,9 @@ public:
using AboutToShowContextMenuHandler = std::function<void (Utils::PathChooser *, QMenu *)>; using AboutToShowContextMenuHandler = std::function<void (Utils::PathChooser *, QMenu *)>;
static void setAboutToShowContextMenuHandler(AboutToShowContextMenuHandler handler); static void setAboutToShowContextMenuHandler(AboutToShowContextMenuHandler handler);
QColor errorColor() const;
QColor okColor() const;
private: private:
bool validatePath(FancyLineEdit *edit, QString *errorMessage) const; bool validatePath(FancyLineEdit *edit, QString *errorMessage) const;
// Returns overridden title or the one from <title> // Returns overridden title or the one from <title>
@@ -165,6 +170,9 @@ public slots:
void setPath(const QString &); void setPath(const QString &);
void setFileName(const Utils::FileName &); void setFileName(const Utils::FileName &);
void setErrorColor(const QColor &errorColor);
void setOkColor(const QColor &okColor);
private: private:
PathChooserPrivate *d; PathChooserPrivate *d;
static AboutToShowContextMenuHandler s_aboutToShowContextMenuHandler; static AboutToShowContextMenuHandler s_aboutToShowContextMenuHandler;

View File

@@ -28,25 +28,17 @@
** **
****************************************************************************/ ****************************************************************************/
#include "customwizardpreprocessor.h" #include "templateengine.h"
#ifdef WITH_TESTS
# include "../projectexplorer.h"
# include <QTest>
#endif
#include <utils/qtcassert.h> #include "qtcassert.h"
#include <QStringList>
#include <QStack>
#include <QRegExp>
#include <QDebug>
#include <QJSEngine> #include <QJSEngine>
#include <QStack>
namespace Utils {
namespace ProjectExplorer {
namespace Internal { namespace Internal {
enum { debug = 0 };
// Preprocessor: Conditional section type. // Preprocessor: Conditional section type.
enum PreprocessorSection { enum PreprocessorSection {
IfSection, IfSection,
@@ -58,7 +50,8 @@ enum PreprocessorSection {
// Preprocessor: Section stack entry containing nested '@if' section // Preprocessor: Section stack entry containing nested '@if' section
// state. // state.
struct PreprocessStackEntry { class PreprocessStackEntry {
public:
PreprocessStackEntry(PreprocessorSection section = OtherSection, PreprocessStackEntry(PreprocessorSection section = OtherSection,
bool parentEnabled = true, bool parentEnabled = true,
bool condition = false, bool condition = false,
@@ -70,11 +63,9 @@ struct PreprocessStackEntry {
bool anyIfClauseMatched; // Determines if 'else' triggers bool anyIfClauseMatched; // Determines if 'else' triggers
}; };
PreprocessStackEntry::PreprocessStackEntry(PreprocessorSection s, PreprocessStackEntry::PreprocessStackEntry(PreprocessorSection s, bool p, bool c, bool a) :
bool p, bool c, bool a) :
section(s), parentEnabled(p), condition(c), anyIfClauseMatched(a) section(s), parentEnabled(p), condition(c), anyIfClauseMatched(a)
{ { }
}
// Context for preprocessing. // Context for preprocessing.
class PreprocessContext { class PreprocessContext {
@@ -102,13 +93,14 @@ PreprocessContext::PreprocessContext() :
m_elsePattern(QLatin1String("^[\\s]*@[\\s]*else.*$")), m_elsePattern(QLatin1String("^[\\s]*@[\\s]*else.*$")),
m_endifPattern(QLatin1String("^[\\s]*@[\\s]*endif.*$")) m_endifPattern(QLatin1String("^[\\s]*@[\\s]*endif.*$"))
{ {
QTC_ASSERT(m_ifPattern.isValid() && m_elsifPattern.isValid() QTC_CHECK(m_ifPattern.isValid() && m_elsifPattern.isValid()
&& m_elsePattern.isValid() &&m_endifPattern.isValid(), return); && m_elsePattern.isValid() && m_endifPattern.isValid());
} }
void PreprocessContext::reset() void PreprocessContext::reset()
{ {
m_sectionStack.clear(); // Add a default, enabled section. m_sectionStack.clear();
// Add a default, enabled section.
m_sectionStack.push(PreprocessStackEntry(OtherSection, true, true)); m_sectionStack.push(PreprocessStackEntry(OtherSection, true, true));
} }
@@ -135,35 +127,6 @@ PreprocessorSection PreprocessContext::preprocessorLine(const QString &in,
return OtherSection; return OtherSection;
} }
// Evaluate an expression within an 'if'/'elsif' to a bool via QJSEngine
bool evaluateBooleanJavaScriptExpression(QJSEngine &engine, const QString &expression, bool *result, QString *errorMessage)
{
errorMessage->clear();
*result = false;
const QJSValue value = engine.evaluate(expression);
if (value.isError()) {
*errorMessage = QString::fromLatin1("Error in \"%1\": %2").
arg(expression, value.toString());
return false;
}
// Try to convert to bool, be that an int or whatever.
if (value.isBool()) {
*result = value.toBool();
return true;
}
if (value.isNumber()) {
*result = !qFuzzyCompare(value.toNumber(), 0);
return true;
}
if (value.isString()) {
*result = !value.toString().isEmpty();
return true;
}
*errorMessage = QString::fromLatin1("Cannot convert result of \"%1\" (\"%2\"to bool.").
arg(expression, value.toString());
return false;
}
static inline QString msgEmptyStack(int line) static inline QString msgEmptyStack(int line)
{ {
return QString::fromLatin1("Unmatched '@endif' at line %1.").arg(line); return QString::fromLatin1("Unmatched '@endif' at line %1.").arg(line);
@@ -184,6 +147,7 @@ bool PreprocessContext::process(const QString &in, QString *out, QString *errorM
for (int l = 0; l < lineCount; l++) { for (int l = 0; l < lineCount; l++) {
// Check for element of the stack (be it dummy, else something is wrong). // Check for element of the stack (be it dummy, else something is wrong).
if (m_sectionStack.isEmpty()) { if (m_sectionStack.isEmpty()) {
if (errorMessage)
*errorMessage = msgEmptyStack(l); *errorMessage = msgEmptyStack(l);
return false; return false;
} }
@@ -195,32 +159,33 @@ bool PreprocessContext::process(const QString &in, QString *out, QString *errorM
case IfSection: case IfSection:
// '@If': Push new section // '@If': Push new section
if (top.condition) { if (top.condition) {
if (!evaluateBooleanJavaScriptExpression(m_scriptEngine, expression, &expressionValue, errorMessage)) { if (!TemplateEngine::evaluateBooleanJavaScriptExpression(m_scriptEngine, expression,
*errorMessage = QString::fromLatin1("Error in @if at %1: %2"). &expressionValue, errorMessage)) {
arg(l + 1).arg(*errorMessage); if (errorMessage)
*errorMessage = QString::fromLatin1("Error in @if at %1: %2")
.arg(l + 1).arg(*errorMessage);
return false; return false;
} }
} }
if (debug)
qDebug("'%s' : expr='%s' -> %d", qPrintable(lines.at(l)), qPrintable(expression), expressionValue);
m_sectionStack.push(PreprocessStackEntry(IfSection, m_sectionStack.push(PreprocessStackEntry(IfSection,
top.condition, expressionValue, expressionValue)); top.condition, expressionValue, expressionValue));
break; break;
case ElsifSection: // '@elsif': Check condition. case ElsifSection: // '@elsif': Check condition.
if (top.section != IfSection && top.section != ElsifSection) { if (top.section != IfSection && top.section != ElsifSection) {
*errorMessage = QString::fromLatin1("No preceding @if found for @elsif at %1"). if (errorMessage)
arg(l + 1); *errorMessage = QString::fromLatin1("No preceding @if found for @elsif at %1")
.arg(l + 1);
return false; return false;
} }
if (top.parentEnabled) { if (top.parentEnabled) {
if (!evaluateBooleanJavaScriptExpression(m_scriptEngine, expression, &expressionValue, errorMessage)) { if (!TemplateEngine::evaluateBooleanJavaScriptExpression(m_scriptEngine, expression,
*errorMessage = QString::fromLatin1("Error in @elsif at %1: %2"). &expressionValue, errorMessage)) {
arg(l + 1).arg(*errorMessage); if (errorMessage)
*errorMessage = QString::fromLatin1("Error in @elsif at %1: %2")
.arg(l + 1).arg(*errorMessage);
return false; return false;
} }
} }
if (debug)
qDebug("'%s' : expr='%s' -> %d", qPrintable(lines.at(l)), qPrintable(expression), expressionValue);
top.section = ElsifSection; top.section = ElsifSection;
// ignore consecutive '@elsifs' once something matched // ignore consecutive '@elsifs' once something matched
if (top.anyIfClauseMatched) { if (top.anyIfClauseMatched) {
@@ -232,13 +197,12 @@ bool PreprocessContext::process(const QString &in, QString *out, QString *errorM
break; break;
case ElseSection: // '@else': Check condition. case ElseSection: // '@else': Check condition.
if (top.section != IfSection && top.section != ElsifSection) { if (top.section != IfSection && top.section != ElsifSection) {
*errorMessage = QString::fromLatin1("No preceding @if/@elsif found for @else at %1"). if (errorMessage)
arg(l + 1); *errorMessage = QString::fromLatin1("No preceding @if/@elsif found for @else at %1")
.arg(l + 1);
return false; return false;
} }
expressionValue = top.parentEnabled && !top.anyIfClauseMatched; expressionValue = top.parentEnabled && !top.anyIfClauseMatched;
if (debug)
qDebug("%s -> %d", qPrintable(lines.at(l)), expressionValue);
top.section = ElseSection; top.section = ElseSection;
top.condition = expressionValue; top.condition = expressionValue;
break; break;
@@ -247,8 +211,9 @@ bool PreprocessContext::process(const QString &in, QString *out, QString *errorM
break; break;
case OtherSection: // Rest: Append according to current condition. case OtherSection: // Rest: Append according to current condition.
if (top.condition) { if (top.condition) {
out->append(lines.at(l)); if (l != 0)
out->append(newLine); out->append(newLine);
out->append(lines.at(l));
} }
break; break;
} // switch section } // switch section
@@ -257,97 +222,96 @@ bool PreprocessContext::process(const QString &in, QString *out, QString *errorM
return true; return true;
} }
/*! } // namespace Internal
Implements a custom wizard preprocessor based on JavaScript expressions.
Preprocesses a string using a simple syntax: bool TemplateEngine::preprocessText(const QString &in, QString *out, QString *errorMessage)
\code
Text
@if <JavaScript-expression>
Bla...
@elsif <JavaScript-expression2>
Blup
@endif
\endcode
The JavaScript-expressions must evaluate to integers or boolean, like
\c '2 == 1 + 1', \c '"a" == "a"'. The variables of the custom wizard will be
expanded before, so \c "%VAR%" should be used for strings and \c %VAR% for integers.
\sa ProjectExplorer::CustomWizard
*/
bool customWizardPreprocess(const QString &in, QString *out, QString *errorMessage)
{ {
PreprocessContext context; Internal::PreprocessContext context;
return context.process(in, out, errorMessage); return context.process(in, out, errorMessage);
} }
} // namespace Internal QString TemplateEngine::processText(MacroExpander *expander, const QString &input,
QString *errorMessage)
#ifdef WITH_TESTS // Run qtcreator -test ProjectExplorer
void ProjectExplorerPlugin::testCustomWizardPreprocessor_data()
{ {
QTest::addColumn<QString>("input"); if (errorMessage)
QTest::addColumn<QString>("expectedOutput"); errorMessage->clear();
QTest::addColumn<bool>("expectedSuccess");
QTest::addColumn<QString>("expectedErrorMessage"); if (input.isEmpty())
QTest::newRow("if") return input;
<< QString::fromLatin1("@if 1\nline 1\n@elsif 0\nline 2\n@else\nline 3\n@endif\n")
<< QString::fromLatin1("line 1") // Recursively expand macros:
<< true << QString(); QString in = input;
QTest::newRow("elsif") QString oldIn;
<< QString::fromLatin1("@if 0\nline 1\n@elsif 1\nline 2\n@else\nline 3\n@endif\n") for (int i = 0; i < 5 && in != oldIn; ++i) {
<< QString::fromLatin1("line 2") oldIn = in;
<< true << QString(); in = expander->expand(oldIn);
QTest::newRow("else") }
<< QString::fromLatin1("@if 0\nline 1\n@elsif 0\nline 2\n@else\nline 3\n@endif\n")
<< QString::fromLatin1("line 3") QString out;
<< true << QString(); if (!preprocessText(in, &out, errorMessage))
QTest::newRow("nested-if") return QString();
<< QString::fromLatin1("@if 1\n"
" @if 1\nline 1\n@elsif 0\nline 2\n@else\nline 3\n@endif\n" // Expand \n, \t and handle line continuation:
"@else\n" QString result;
" @if 1\nline 4\n@elsif 0\nline 5\n@else\nline 6\n@endif\n" result.reserve(out.count());
"@endif\n") bool isEscaped = false;
<< QString::fromLatin1("line 1") for (int i = 0; i < out.count(); ++i) {
<< true << QString(); const QChar c = out.at(i);
QTest::newRow("nested-else")
<< QString::fromLatin1("@if 0\n" if (isEscaped) {
" @if 1\nline 1\n@elsif 0\nline 2\n@else\nline 3\n@endif\n" if (c == QLatin1Char('n'))
"@else\n" result.append(QLatin1Char('\n'));
" @if 1\nline 4\n@elsif 0\nline 5\n@else\nline 6\n@endif\n" else if (c == QLatin1Char('t'))
"@endif\n") result.append(QLatin1Char('\t'));
<< QString::fromLatin1("line 4") else if (c != QLatin1Char('\n'))
<< true << QString(); result.append(c);
QTest::newRow("twice-nested-if") isEscaped = false;
<< QString::fromLatin1("@if 0\n" } else {
" @if 1\n" if (c == QLatin1Char('\\'))
" @if 1\nline 1\n@else\nline 2\n@endif\n" isEscaped = true;
" @endif\n" else
"@else\n" result.append(c);
" @if 1\n" }
" @if 1\nline 3\n@else\nline 4\n@endif\n" }
" @endif\n" return result;
"@endif\n")
<< QString::fromLatin1("line 3")
<< true << QString();
} }
void ProjectExplorerPlugin::testCustomWizardPreprocessor() bool TemplateEngine::evaluateBooleanJavaScriptExpression(QJSEngine &engine,
const QString &expression, bool *result,
QString *errorMessage)
{ {
QFETCH(QString, input); if (errorMessage)
QFETCH(QString, expectedOutput); errorMessage->clear();
QFETCH(bool, expectedSuccess); if (result)
QFETCH(QString, expectedErrorMessage); *result = false;
const QJSValue value = engine.evaluate(expression);
if (value.isError()) {
if (errorMessage)
*errorMessage = QString::fromLatin1("Error in \"%1\": %2")
.arg(expression, value.toString());
return false;
}
// Try to convert to bool, be that an int or whatever.
if (value.isBool()) {
if (result)
*result = value.toBool();
return true;
}
if (value.isNumber()) {
if (result)
*result = !qFuzzyCompare(value.toNumber(), 0);
return true;
}
if (value.isString()) {
if (result)
*result = !value.toString().isEmpty();
return true;
}
if (errorMessage)
*errorMessage = QString::fromLatin1("Cannot convert result of \"%1\" (\"%2\"to bool.")
.arg(expression, value.toString());
QString errorMessage; return false;
QString output;
const bool success = Internal::customWizardPreprocess(input, &output, &errorMessage);
QCOMPARE(success, expectedSuccess);
QCOMPARE(output.trimmed(), expectedOutput.trimmed());
QCOMPARE(errorMessage, expectedErrorMessage);
} }
#endif // WITH_TESTS
} // namespace ProjectExplorer } // namespace Utils

View File

@@ -28,20 +28,30 @@
** **
****************************************************************************/ ****************************************************************************/
#ifndef CUSTOMWIZARDPREPROCESSOR_H #ifndef TEMPLATEENGINE_H
#define CUSTOMWIZARDPREPROCESSOR_H #define TEMPLATEENGINE_H
#include "utils_global.h"
#include "macroexpander.h"
#include <QString> #include <QString>
QT_FORWARD_DECLARE_CLASS(QJSEngine) QT_FORWARD_DECLARE_CLASS(QJSEngine);
namespace ProjectExplorer { namespace Utils {
namespace Internal {
bool customWizardPreprocess(const QString &in, QString *out, QString *errorMessage); class QTCREATOR_UTILS_EXPORT TemplateEngine {
/* Helper to evaluate an expression. */ public:
bool evaluateBooleanJavaScriptExpression(QJSEngine &engine, const QString &expression, bool *result, QString *errorMessage); static bool preprocessText(const QString &input, QString *output, QString *errorMessage);
} // namespace Internal
} // namespace ProjectExplorer
#endif // CUSTOMWIZARDPREPROCESSOR_H static QString processText(MacroExpander *expander, const QString &input,
QString *errorMessage);
static bool evaluateBooleanJavaScriptExpression(QJSEngine &engine, const QString &expression,
bool *result, QString *errorMessage);
};
} // namespace Utils
#endif // TEMPLATEENGINE_H

View File

@@ -4,7 +4,7 @@ dll {
DEFINES += QTCREATOR_UTILS_STATIC_LIB DEFINES += QTCREATOR_UTILS_STATIC_LIB
} }
QT += network QT += gui network qml
CONFIG += exceptions # used by portlist.cpp, textfileformat.cpp, and ssh/* CONFIG += exceptions # used by portlist.cpp, textfileformat.cpp, and ssh/*
@@ -16,6 +16,7 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/shellcommandpage.cpp \ $$PWD/shellcommandpage.cpp \
$$PWD/settingsselector.cpp \ $$PWD/settingsselector.cpp \
$$PWD/stringutils.cpp \ $$PWD/stringutils.cpp \
$$PWD/templateengine.cpp \
$$PWD/textfieldcheckbox.cpp \ $$PWD/textfieldcheckbox.cpp \
$$PWD/textfieldcombobox.cpp \ $$PWD/textfieldcombobox.cpp \
$$PWD/filesearch.cpp \ $$PWD/filesearch.cpp \
@@ -108,6 +109,7 @@ HEADERS += \
$$PWD/shellcommand.h \ $$PWD/shellcommand.h \
$$PWD/shellcommandpage.h \ $$PWD/shellcommandpage.h \
$$PWD/stringutils.h \ $$PWD/stringutils.h \
$$PWD/templateengine.h \
$$PWD/textfieldcheckbox.h \ $$PWD/textfieldcheckbox.h \
$$PWD/textfieldcombobox.h \ $$PWD/textfieldcombobox.h \
$$PWD/filesearch.h \ $$PWD/filesearch.h \

View File

@@ -1,5 +1,3 @@
QT += gui network
include(../../qtcreatorlibrary.pri) include(../../qtcreatorlibrary.pri)
include(utils-lib.pri) include(utils-lib.pri)

View File

@@ -28,7 +28,7 @@ QtcLibrary {
cpp.frameworks: ["Foundation"] cpp.frameworks: ["Foundation"]
} }
Depends { name: "Qt"; submodules: ["widgets", "network", "script", "concurrent"] } Depends { name: "Qt"; submodules: ["concurrent", "network", "qml", "widgets"] }
Depends { name: "app_version_header" } Depends { name: "app_version_header" }
files: [ files: [
@@ -189,6 +189,8 @@ QtcLibrary {
"synchronousprocess.h", "synchronousprocess.h",
"tcpportsgatherer.cpp", "tcpportsgatherer.cpp",
"tcpportsgatherer.h", "tcpportsgatherer.h",
"templateengine.cpp",
"templateengine.h",
"textfieldcheckbox.cpp", "textfieldcheckbox.cpp",
"textfieldcheckbox.h", "textfieldcheckbox.h",
"textfieldcombobox.cpp", "textfieldcombobox.cpp",

View File

@@ -70,15 +70,15 @@ bool AnalyzerAction::isRunnable(QString *reason) const
return ProjectExplorerPlugin::canRun(SessionManager::startupProject(), m_runMode, reason); return ProjectExplorerPlugin::canRun(SessionManager::startupProject(), m_runMode, reason);
} }
static bool buildTypeAccepted(ToolMode toolMode, BuildConfiguration::BuildType buildType) static bool buildTypeAccepted(QFlags<ToolMode> toolMode, BuildConfiguration::BuildType buildType)
{ {
if (toolMode == AnyMode)
return true;
if (buildType == BuildConfiguration::Unknown) if (buildType == BuildConfiguration::Unknown)
return true; return true;
if (buildType == BuildConfiguration::Debug && toolMode == DebugMode) if (buildType == BuildConfiguration::Debug && (toolMode & DebugMode))
return true; return true;
if (buildType == BuildConfiguration::Release && toolMode == ReleaseMode) if (buildType == BuildConfiguration::Release && (toolMode & ReleaseMode))
return true;
if (buildType == BuildConfiguration::Profile && (toolMode & ProfileMode))
return true; return true;
return false; return false;
} }
@@ -114,30 +114,53 @@ void AnalyzerAction::startTool()
// Check the project for whether the build config is in the correct mode // Check the project for whether the build config is in the correct mode
// if not, notify the user and urge him to use the correct mode. // if not, notify the user and urge him to use the correct mode.
if (!buildTypeAccepted(m_toolMode, buildType)) { if (!buildTypeAccepted(m_toolMode, buildType)) {
const QString currentMode = buildType == BuildConfiguration::Debug QString currentMode;
? AnalyzerManager::tr("Debug") switch (buildType) {
: AnalyzerManager::tr("Release"); case BuildConfiguration::Debug:
currentMode = AnalyzerManager::tr("Debug");
QString toolModeString;
switch (m_toolMode) {
case DebugMode:
toolModeString = AnalyzerManager::tr("Debug");
break; break;
case ReleaseMode: case BuildConfiguration::Profile:
toolModeString = AnalyzerManager::tr("Release"); currentMode = AnalyzerManager::tr("Profile");
break;
case BuildConfiguration::Release:
currentMode = AnalyzerManager::tr("Release");
break; break;
default: default:
QTC_CHECK(false); QTC_CHECK(false);
} }
//const QString toolName = displayName();
const QString toolName = AnalyzerManager::tr("Tool"); // FIXME QString toolModeString;
switch (m_toolMode) {
case DebugMode:
toolModeString = AnalyzerManager::tr("in Debug mode");
break;
case ProfileMode:
toolModeString = AnalyzerManager::tr("in Profile mode");
break;
case ReleaseMode:
toolModeString = AnalyzerManager::tr("in Release mode");
break;
case SymbolsMode:
toolModeString = AnalyzerManager::tr("with debug symbols (Debug or Profile mode)");
break;
case OptimizedMode:
toolModeString = AnalyzerManager::tr("on optimized code (Profile or Release mode)");
break;
default:
QTC_CHECK(false);
}
const QString toolName = text(); // The action text is always the name of the tool
const QString title = AnalyzerManager::tr("Run %1 in %2 Mode?").arg(toolName).arg(currentMode); const QString title = AnalyzerManager::tr("Run %1 in %2 Mode?").arg(toolName).arg(currentMode);
const QString message = AnalyzerManager::tr("<html><head/><body><p>You are trying " const QString message = AnalyzerManager::tr("<html><head/><body><p>You are trying "
"to run the tool \"%1\" on an application in %2 mode. " "to run the tool \"%1\" on an application in %2 mode. "
"The tool is designed to be used in %3 mode.</p><p>" "The tool is designed to be used %3.</p><p>"
"Debug and Release mode run-time characteristics differ " "Run-time characteristics differ significantly between "
"significantly, analytical findings for one mode may or " "optimized and non-optimized binaries. Analytical "
"may not be relevant for the other.</p><p>" "findings for one mode may or may not be relevant for "
"the other.</p><p>"
"Running tools that need debug symbols on binaries that "
"don't provide any may lead to missing function names "
"or otherwise insufficient output.</p><p>"
"Do you want to continue and run the tool in %2 mode?</p></body></html>") "Do you want to continue and run the tool in %2 mode?</p></body></html>")
.arg(toolName).arg(currentMode).arg(toolModeString); .arg(toolName).arg(currentMode).arg(toolModeString);
if (Utils::CheckableMessageBox::doNotAskAgainQuestion(ICore::mainWindow(), if (Utils::CheckableMessageBox::doNotAskAgainQuestion(ICore::mainWindow(),

View File

@@ -53,15 +53,20 @@ class AnalyzerRunControl;
/** /**
* The mode in which this tool should preferably be run * The mode in which this tool should preferably be run
* *
* The memcheck tool, for example, requires debug symbols, hence DebugMode * Debugging tools which try to show stack traces as close as possible to what the source code
* is preferred. On the other hand, callgrind should look at optimized code, * looks like will prefer SymbolsMode. Profiling tools which need optimized code for realistic
* hence ReleaseMode. * performance, but still want to show analytical output that depends on debug symbols, will prefer
* ProfileMode.
*/ */
enum ToolMode { enum ToolMode {
DebugMode, DebugMode = 0x1,
ReleaseMode, ProfileMode = 0x2,
AnyMode ReleaseMode = 0x4,
SymbolsMode = DebugMode | ProfileMode,
OptimizedMode = ProfileMode | ReleaseMode,
AnyMode = DebugMode | ProfileMode | ReleaseMode
}; };
Q_DECLARE_FLAGS(ToolModes, ToolMode)
/** /**
* This class represents an analyzation action, i.e. a tool that runs in a specific mode. * This class represents an analyzation action, i.e. a tool that runs in a specific mode.
@@ -84,7 +89,7 @@ public:
Core::Id toolId() const { return m_toolId; } Core::Id toolId() const { return m_toolId; }
void setToolId(Core::Id id) { m_toolId = id; } void setToolId(Core::Id id) { m_toolId = id; }
void setToolMode(ToolMode mode) { m_toolMode = mode; } void setToolMode(QFlags<ToolMode> mode) { m_toolMode = mode; }
Core::Id runMode() const { return m_runMode; } Core::Id runMode() const { return m_runMode; }
void setRunMode(Core::Id mode) { m_runMode = mode; } void setRunMode(Core::Id mode) { m_runMode = mode; }
@@ -118,7 +123,7 @@ protected:
Core::Id m_menuGroup; Core::Id m_menuGroup;
Core::Id m_actionId; Core::Id m_actionId;
Core::Id m_toolId; Core::Id m_toolId;
ToolMode m_toolMode; QFlags<ToolMode> m_toolMode;
Core::Id m_runMode; Core::Id m_runMode;
WidgetCreator m_widgetCreator; WidgetCreator m_widgetCreator;
RunControlCreator m_runControlCreator; RunControlCreator m_runControlCreator;

View File

@@ -114,8 +114,9 @@ bool AndroidBuildApkStep::init()
} }
if (bc->buildType() == ProjectExplorer::BuildConfiguration::Debug) if (bc->buildType() != ProjectExplorer::BuildConfiguration::Release)
emit addOutput(tr("Warning: Signing a debug package."), BuildStep::ErrorMessageOutput); emit addOutput(tr("Warning: Signing a debug or profile package."),
BuildStep::ErrorMessageOutput);
} }
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit()); QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());

View File

@@ -243,8 +243,9 @@ void AndroidBuildApkWidget::verboseOutputCheckBoxToggled(bool checked)
void AndroidBuildApkWidget::updateSigningWarning() void AndroidBuildApkWidget::updateSigningWarning()
{ {
bool debug = m_step->buildConfiguration()->buildType() == ProjectExplorer::BuildConfiguration::Debug; bool nonRelease = m_step->buildConfiguration()->buildType()
if (m_step->signPackage() && debug) { != ProjectExplorer::BuildConfiguration::Release;
if (m_step->signPackage() && nonRelease) {
m_ui->signingDebugWarningIcon->setVisible(true); m_ui->signingDebugWarningIcon->setVisible(true);
m_ui->signingDebugWarningLabel->setVisible(true); m_ui->signingDebugWarningLabel->setVisible(true);
} else { } else {

View File

@@ -258,8 +258,9 @@ AndroidToolChainFactory::AndroidToolChainFactory()
setDisplayName(tr("Android GCC")); setDisplayName(tr("Android GCC"));
} }
QList<ToolChain *> AndroidToolChainFactory::autoDetect() QList<ToolChain *> AndroidToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
{ {
Q_UNUSED(alreadyKnown);
return createToolChainsForNdk(AndroidConfigurations::currentConfig().ndkLocation()); return createToolChainsForNdk(AndroidConfigurations::currentConfig().ndkLocation());
} }

View File

@@ -101,7 +101,7 @@ class AndroidToolChainFactory : public ProjectExplorer::ToolChainFactory
public: public:
AndroidToolChainFactory(); AndroidToolChainFactory();
QList<ProjectExplorer::ToolChain *> autoDetect() override; QList<ProjectExplorer::ToolChain *> autoDetect(const QList<ProjectExplorer::ToolChain *> &alreadyKnown) override;
bool canRestore(const QVariantMap &data) override; bool canRestore(const QVariantMap &data) override;
ProjectExplorer::ToolChain *restore(const QVariantMap &data) override; ProjectExplorer::ToolChain *restore(const QVariantMap &data) override;

View File

@@ -66,6 +66,7 @@
#include <clangbackendipc/projectpartsdonotexistmessage.h> #include <clangbackendipc/projectpartsdonotexistmessage.h>
#include <clangbackendipc/translationunitdoesnotexistmessage.h> #include <clangbackendipc/translationunitdoesnotexistmessage.h>
#include <clangbackendipc/unregisterunsavedfilesforeditormessage.h> #include <clangbackendipc/unregisterunsavedfilesforeditormessage.h>
#include <clangbackendipc/updatetranslationunitsforeditormessage.h>
#include <cplusplus/Icons.h> #include <cplusplus/Icons.h>
@@ -194,6 +195,7 @@ public:
void end() override; void end() override;
void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &message) override; void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &message) override;
void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &message) override;
void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &message) override; void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &message) override;
void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) override; void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) override;
void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) override; void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) override;
@@ -218,6 +220,12 @@ void IpcSender::registerTranslationUnitsForEditor(const RegisterTranslationUnitF
m_connection.serverProxy().registerTranslationUnitsForEditor(message); m_connection.serverProxy().registerTranslationUnitsForEditor(message);
} }
void IpcSender::updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &message)
{
QTC_CHECK(m_connection.isConnected());
m_connection.serverProxy().updateTranslationUnitsForEditor(message);
}
void IpcSender::unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message) void IpcSender::unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message)
{ {
QTC_CHECK(m_connection.isConnected()); QTC_CHECK(m_connection.isConnected());
@@ -368,6 +376,16 @@ void IpcCommunicator::registerProjectsParts(const QList<CppTools::ProjectPart::P
registerProjectPartsForEditor(projectPartContainers); registerProjectPartsForEditor(projectPartContainers);
} }
void IpcCommunicator::registerTranslationUnit(TextEditor::TextDocument *document)
{
const QString filePath = document->filePath().toString();
const QString projectPartId = Utils::projectPartIdForFile(filePath);
registerTranslationUnitsForEditor({{Utf8String(filePath),
Utf8String(projectPartId),
uint(document->document()->revision())}});
}
void IpcCommunicator::updateTranslationUnitFromCppEditorDocument(const QString &filePath) void IpcCommunicator::updateTranslationUnitFromCppEditorDocument(const QString &filePath)
{ {
const auto document = CppTools::CppModelManager::instance()->cppEditorDocument(filePath); const auto document = CppTools::CppModelManager::instance()->cppEditorDocument(filePath);
@@ -388,34 +406,33 @@ CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath)
return CppTools::CppModelManager::instance()->cppEditorDocument(filePath); return CppTools::CppModelManager::instance()->cppEditorDocument(filePath);
} }
bool documentHasChanged(const QString &filePath, const QString &projectPartId) bool documentHasChanged(const QString &filePath)
{ {
auto *document = cppDocument(filePath); auto *document = cppDocument(filePath);
if (document) if (document)
return document->sendTracker(projectPartId).shouldSendRevision(document->revision()); return document->sendTracker().shouldSendRevision(document->revision());
return true; return true;
} }
void setLastSentDocumentRevision(const QString &filePath, void setLastSentDocumentRevision(const QString &filePath,
const QString &projectPartId,
uint revision) uint revision)
{ {
auto *document = cppDocument(filePath); auto *document = cppDocument(filePath);
if (document) if (document)
document->sendTracker(projectPartId).setLastSentRevision(int(revision)); document->sendTracker().setLastSentRevision(int(revision));
} }
} }
void IpcCommunicator::updateTranslationUnit(const QString &filePath, void IpcCommunicator::registerTranslationUnit(const QString &filePath,
const QByteArray &contents, const QByteArray &contents,
uint documentRevision) uint documentRevision)
{ {
const QString projectPartId = Utils::projectPartIdForFile(filePath); const QString projectPartId = Utils::projectPartIdForFile(filePath);
if (documentHasChanged(filePath, projectPartId)) { if (documentHasChanged(filePath)) {
const bool hasUnsavedContent = true; const bool hasUnsavedContent = true;
registerTranslationUnitsForEditor({{filePath, registerTranslationUnitsForEditor({{filePath,
@@ -424,18 +441,30 @@ void IpcCommunicator::updateTranslationUnit(const QString &filePath,
hasUnsavedContent, hasUnsavedContent,
documentRevision}}); documentRevision}});
setLastSentDocumentRevision(filePath, projectPartId, documentRevision); setLastSentDocumentRevision(filePath, documentRevision);
} }
} }
void IpcCommunicator::updateTranslationUnit(const QString &filePath,
const QByteArray &contents,
uint documentRevision)
{
const bool hasUnsavedContent = true;
updateTranslationUnitsForEditor({{filePath,
Utf8String(),
Utf8String::fromByteArray(contents),
hasUnsavedContent,
documentRevision}});
}
void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision) void IpcCommunicator::updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision)
{ {
const QString projectPartId = Utils::projectPartIdForFile(filePath);
const bool hasUnsavedContent = true; const bool hasUnsavedContent = true;
// TODO: Send new only if changed // TODO: Send new only if changed
registerUnsavedFilesForEditor({{filePath, registerUnsavedFilesForEditor({{filePath,
projectPartId, Utf8String(),
Utf8String::fromByteArray(contents), Utf8String::fromByteArray(contents),
hasUnsavedContent, hasUnsavedContent,
documentRevision}}); documentRevision}});
@@ -446,27 +475,35 @@ void IpcCommunicator::requestDiagnostics(const FileContainer &fileContainer)
if (m_sendMode == IgnoreSendRequests) if (m_sendMode == IgnoreSendRequests)
return; return;
if (documentHasChanged(fileContainer.filePath(), fileContainer.projectPartId())) { if (documentHasChanged(fileContainer.filePath())) {
registerTranslationUnitsForEditor({fileContainer}); updateTranslationUnitsForEditor({fileContainer});
const RequestDiagnosticsMessage message(fileContainer); const RequestDiagnosticsMessage message(fileContainer);
qCDebug(log) << ">>>" << message; qCDebug(log) << ">>>" << message;
m_ipcSender->requestDiagnostics(message); m_ipcSender->requestDiagnostics(message);
setLastSentDocumentRevision(fileContainer.filePath(), setLastSentDocumentRevision(fileContainer.filePath(),
fileContainer.projectPartId(),
fileContainer.documentRevision()); fileContainer.documentRevision());
} }
} }
void IpcCommunicator::requestDiagnostics(Core::IDocument *document)
{
const auto textDocument = qobject_cast<TextDocument*>(document);
const auto filePath = textDocument->filePath().toString();
const QString projectPartId = Utils::projectPartIdForFile(filePath);
requestDiagnostics(FileContainer(filePath,
projectPartId,
textDocument->document()->revision()));
}
void IpcCommunicator::updateChangeContentStartPosition(const QString &filePath, int position) void IpcCommunicator::updateChangeContentStartPosition(const QString &filePath, int position)
{ {
auto *document = cppDocument(filePath); auto *document = cppDocument(filePath);
if (document) { if (document)
const QString projectPartId = Utils::projectPartIdForFile(filePath); document->sendTracker().applyContentChange(position);
document->sendTracker(projectPartId).applyContentChange(position);
}
} }
void IpcCommunicator::updateTranslationUnitIfNotCurrentDocument(Core::IDocument *document) void IpcCommunicator::updateTranslationUnitIfNotCurrentDocument(Core::IDocument *document)
@@ -540,6 +577,16 @@ void IpcCommunicator::registerTranslationUnitsForEditor(const FileContainers &fi
m_ipcSender->registerTranslationUnitsForEditor(message); m_ipcSender->registerTranslationUnitsForEditor(message);
} }
void IpcCommunicator::updateTranslationUnitsForEditor(const IpcCommunicator::FileContainers &fileContainers)
{
if (m_sendMode == IgnoreSendRequests)
return;
const UpdateTranslationUnitsForEditorMessage message(fileContainers);
qCDebug(log) << ">>>" << message;
m_ipcSender->updateTranslationUnitsForEditor(message);
}
void IpcCommunicator::unregisterTranslationUnitsForEditor(const FileContainers &fileContainers) void IpcCommunicator::unregisterTranslationUnitsForEditor(const FileContainers &fileContainers)
{ {
if (m_sendMode == IgnoreSendRequests) if (m_sendMode == IgnoreSendRequests)

View File

@@ -53,6 +53,7 @@ class DiagnosticsChangedMessage;
namespace TextEditor { namespace TextEditor {
class TextEditorWidget; class TextEditorWidget;
class TextDocument;
} }
namespace ClangCodeModel { namespace ClangCodeModel {
@@ -96,6 +97,7 @@ public:
virtual void end() = 0; virtual void end() = 0;
virtual void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &message) = 0; virtual void registerTranslationUnitsForEditor(const ClangBackEnd::RegisterTranslationUnitForEditorMessage &message) = 0;
virtual void updateTranslationUnitsForEditor(const ClangBackEnd::UpdateTranslationUnitsForEditorMessage &message) = 0;
virtual void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &message) = 0; virtual void unregisterTranslationUnitsForEditor(const ClangBackEnd::UnregisterTranslationUnitsForEditorMessage &message) = 0;
virtual void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) = 0; virtual void registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) = 0;
virtual void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) = 0; virtual void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) = 0;
@@ -118,6 +120,7 @@ public:
IpcCommunicator(); IpcCommunicator();
void registerTranslationUnitsForEditor(const FileContainers &fileContainers); void registerTranslationUnitsForEditor(const FileContainers &fileContainers);
void updateTranslationUnitsForEditor(const FileContainers &fileContainers);
void unregisterTranslationUnitsForEditor(const FileContainers &fileContainers); void unregisterTranslationUnitsForEditor(const FileContainers &fileContainers);
void registerProjectPartsForEditor(const ProjectPartContainers &projectPartContainers); void registerProjectPartsForEditor(const ProjectPartContainers &projectPartContainers);
void unregisterProjectPartsForEditor(const QStringList &projectPartIds); void unregisterProjectPartsForEditor(const QStringList &projectPartIds);
@@ -130,6 +133,8 @@ public:
void registerProjectsParts(const QList<CppTools::ProjectPart::Ptr> projectParts); void registerProjectsParts(const QList<CppTools::ProjectPart::Ptr> projectParts);
void registerTranslationUnit(TextEditor::TextDocument *document);
void registerTranslationUnit(const QString &filePath, const QByteArray &contents, uint documentRevision);
void updateTranslationUnitIfNotCurrentDocument(Core::IDocument *document); void updateTranslationUnitIfNotCurrentDocument(Core::IDocument *document);
void updateTranslationUnit(Core::IDocument *document); void updateTranslationUnit(Core::IDocument *document);
void updateUnsavedFile(Core::IDocument *document); void updateUnsavedFile(Core::IDocument *document);
@@ -138,6 +143,7 @@ public:
void updateTranslationUnit(const QString &filePath, const QByteArray &contents, uint documentRevision); void updateTranslationUnit(const QString &filePath, const QByteArray &contents, uint documentRevision);
void updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision); void updateUnsavedFile(const QString &filePath, const QByteArray &contents, uint documentRevision);
void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer); void requestDiagnostics(const ClangBackEnd::FileContainer &fileContainer);
void requestDiagnostics(Core::IDocument *document);
void updateChangeContentStartPosition(const QString &filePath, int position); void updateChangeContentStartPosition(const QString &filePath, int position);
public: // for tests public: // for tests

View File

@@ -115,23 +115,14 @@ contains(DEFINES, CLANG_INDEXING) {
FORMS += clangprojectsettingspropertiespage.ui FORMS += clangprojectsettingspropertiespage.ui
equals(TEST, 1) { equals(TEST, 1) {
RESOURCES += \
test/clang_tests_database.qrc
HEADERS += \ HEADERS += \
test/clangcodecompletion_test.h test/clangcodecompletion_test.h
SOURCES += \ SOURCES += \
test/clangcodecompletion_test.cpp test/clangcodecompletion_test.cpp
DISTFILES += \ RESOURCES += test/data/clangtestdata.qrc
test/mysource.cpp \ OTHER_FILES += $$files(test/data/*)
test/myheader.cpp \
test/completionWithProject.cpp \
test/memberCompletion.cpp \
test/doxygenKeywordsCompletion.cpp \
test/preprocessorKeywordsCompletion.cpp \
test/includeDirectiveCompletion.cpp
} }
macx { macx {

View File

@@ -104,7 +104,7 @@ QtcPlugin {
condition: project.testsEnabled condition: project.testsEnabled
prefix: "test/" prefix: "test/"
files: [ files: [
"clang_tests_database.qrc", "data/clangtestdata.qrc",
"clangcodecompletion_test.cpp", "clangcodecompletion_test.cpp",
"clangcodecompletion_test.h", "clangcodecompletion_test.h",
] ]
@@ -112,20 +112,10 @@ QtcPlugin {
Group { Group {
name: "Test resources" name: "Test resources"
prefix: "test/" prefix: "test/data/"
fileTags: "none" fileTags: "none"
files: [ files: [ "*" ]
"mysource.cpp", excludeFiles: "clangtestdata.qrc"
"myheader.h",
"completionWithProject.cpp",
"memberCompletion.cpp",
"doxygenKeywordsCompletion.cpp",
"preprocessorKeywordsCompletion.cpp",
"includeDirectiveCompletion.cpp",
"objc_messages_1.mm",
"objc_messages_2.mm",
"objc_messages_3.mm",
]
} }
files: [ files: [

View File

@@ -670,15 +670,14 @@ ClangCompletionAssistProcessor::unsavedFileContent(const QByteArray &customFileC
return info; return info;
} }
void ClangCompletionAssistProcessor::sendFileContent(const QString &projectPartId, void ClangCompletionAssistProcessor::sendFileContent(const QByteArray &customFileContent)
const QByteArray &customFileContent)
{ {
// TODO: Revert custom modification after the completions // TODO: Revert custom modification after the completions
const UnsavedFileContentInfo info = unsavedFileContent(customFileContent); const UnsavedFileContentInfo info = unsavedFileContent(customFileContent);
IpcCommunicator &ipcCommunicator = m_interface->ipcCommunicator(); IpcCommunicator &ipcCommunicator = m_interface->ipcCommunicator();
ipcCommunicator.registerTranslationUnitsForEditor({{m_interface->fileName(), ipcCommunicator.updateTranslationUnitsForEditor({{m_interface->fileName(),
projectPartId, Utf8String(),
Utf8String::fromByteArray(info.unsavedContent), Utf8String::fromByteArray(info.unsavedContent),
info.isDocumentModified, info.isDocumentModified,
uint(m_interface->textDocument()->revision())}}); uint(m_interface->textDocument()->revision())}});
@@ -690,14 +689,13 @@ CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath)
} }
bool shouldSendDocumentForCompletion(const QString &filePath, bool shouldSendDocumentForCompletion(const QString &filePath,
const QString &projectPartId,
int completionPosition) int completionPosition)
{ {
auto *document = cppDocument(filePath); auto *document = cppDocument(filePath);
if (document) { if (document) {
auto &sendTracker = document->sendTracker(projectPartId); auto &sendTracker = document->sendTracker();
return sendTracker.shouldSendRevisionWithCompletionPosition(document->revision(), return sendTracker.shouldSendRevisionWithCompletionPosition(int(document->revision()),
completionPosition); completionPosition);
} }
@@ -705,14 +703,13 @@ bool shouldSendDocumentForCompletion(const QString &filePath,
} }
void setLastCompletionPositionAndDocumentRevision(const QString &filePath, void setLastCompletionPositionAndDocumentRevision(const QString &filePath,
const QString &projectPartId,
int completionPosition) int completionPosition)
{ {
auto *document = cppDocument(filePath); auto *document = cppDocument(filePath);
if (document) { if (document) {
document->sendTracker(projectPartId).setLastCompletionPosition(completionPosition); document->sendTracker().setLastCompletionPosition(completionPosition);
document->sendTracker(projectPartId).setLastSentRevision(document->revision()); document->sendTracker().setLastSentRevision(document->revision());
} }
} }
@@ -737,13 +734,13 @@ void ClangCompletionAssistProcessor::sendCompletionRequest(int position,
++column; ++column;
const QString filePath = m_interface->fileName(); const QString filePath = m_interface->fileName();
const QString projectPartId = projectPartIdForEditorDocument(filePath);
if (shouldSendDocumentForCompletion(filePath, projectPartId, position)) { if (shouldSendDocumentForCompletion(filePath, position)) {
sendFileContent(projectPartId, customFileContent); sendFileContent(customFileContent);
setLastCompletionPositionAndDocumentRevision(filePath, projectPartId, position); setLastCompletionPositionAndDocumentRevision(filePath, position);
} }
const QString projectPartId = projectPartIdForEditorDocument(filePath);
m_interface->ipcCommunicator().completeCode(this, m_interface->ipcCommunicator().completeCode(this,
filePath, filePath,
uint(line), uint(line),

View File

@@ -83,7 +83,7 @@ private:
}; };
UnsavedFileContentInfo unsavedFileContent(const QByteArray &customFileContent) const; UnsavedFileContentInfo unsavedFileContent(const QByteArray &customFileContent) const;
void sendFileContent(const QString &projectPartId, const QByteArray &customFileContent); void sendFileContent(const QByteArray &customFileContent);
void sendCompletionRequest(int position, const QByteArray &customFileContent); void sendCompletionRequest(int position, const QByteArray &customFileContent);
void handleAvailableCompletions(const CodeCompletions &completions); void handleAvailableCompletions(const CodeCompletions &completions);

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