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/utils/ansiescapecodehandler/tst_ansiescapecodehandler
/tests/auto/utils/fileutils/tst_fileutils
/tests/auto/utils/templateengine/tst_templateengine
/tests/auto/utils_stringutils/tst_utils_stringutils
/tests/auto/valgrind/callgrind/tst_callgrindparsertests
/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.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
You must have Clang installed to use the Clang Static Analyzer. On Windows,
Clang version 3.6, or later, is required to use the MSVC tool chain.
As a tested version of Clang is shipped together with Qt Creator, no manual
setup is required.
To set up the Clang Static Analyzer, select \uicontrol Tools >
\uicontrol Options > \uicontrol Analyzer >
To profit from improved checkers in newer Clang versions, \QC can be set up
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
executable is set correctly in the \uicontrol {Clang executable} field.

View File

@@ -26,7 +26,7 @@
\contentspage {Qt Creator Manual}
\previouspage creator-usability.html
\page creator-coding.html
\nextpage creator-editor-functions.html
\nextpage creator-modeling.html
\title Coding
@@ -34,6 +34,12 @@
\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}
Writing, editing, and navigating in source code are core tasks in

View File

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

View File

@@ -895,7 +895,8 @@
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
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:
@@ -913,7 +914,18 @@
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
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 >
\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,
see \l{Adding New Custom Wizards}.

View File

@@ -76,6 +76,7 @@
\row
\li \b {\l{Coding}}
\list
\li \l{Modeling}
\li \l{Writing Code}
\li \l{Finding}
\li \l{Refactoring}
@@ -195,6 +196,7 @@
\endlist
\li \l{Coding}
\list
\li \l{Modeling}
\li \l{Writing Code}
\list
\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
from glob import glob
import common
ignoreErrors = False
debug_build = False
@@ -50,7 +52,7 @@ def which(program):
if fpath:
if is_exe(program):
return program
if sys.platform.startswith('win'):
if common.is_windows_platform():
if is_exe(program + ".exe"):
return program + ".exe"
else:
@@ -58,7 +60,7 @@ def which(program):
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
if sys.platform.startswith('win'):
if common.is_windows_platform():
if is_exe(exe_file + ".exe"):
return exe_file + ".exe"
@@ -86,44 +88,6 @@ def op_failed(details = None):
else:
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):
ignore_patterns = ['.lib', '.pdb', '.exp', '.ilk']
for ip in ignore_patterns:
@@ -132,7 +96,7 @@ def windows_debug_files_filter(filename):
return False
def copy_ignore_patterns_helper(dir, filenames):
if not sys.platform.startswith('win'):
if not common.is_windows_platform:
return filenames
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):
print "copying Qt libraries..."
if sys.platform.startswith('win'):
if common.is_windows_platform():
libraries = glob(os.path.join(qt_libs_dir, '*.dll'))
else:
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')
else:
dest = os.path.join(install_dir, 'lib', 'qtcreator')
if sys.platform.startswith('win'):
if common.is_windows_platform():
if debug_build:
libraries = filter(lambda library: is_debug(library), libraries)
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)
copy_ignore_func = None
if sys.platform.startswith('win'):
if common.is_windows_platform():
copy_ignore_func = copy_ignore_patterns_helper
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)
pluginPath = os.path.join(qt_plugin_dir, plugin)
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
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)
import_path = os.path.join(qt_import_dir, qtimport)
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)):
print "Copying qt quick 2 imports"
target = os.path.join(install_dir, 'bin', 'qml')
if (os.path.exists(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):
print "Creating qt.conf:"
f = open(install_dir + '/bin/qt.conf', 'w')
def add_qt_conf(target_dir, install_dir):
qtconf_filepath = os.path.join(target_dir, 'qt.conf')
print('Creating qt.conf in "{0}":'.format(qtconf_filepath))
f = open(qtconf_filepath, 'w')
f.write('[Paths]\n')
f.write('Libraries=../lib/qtcreator\n')
f.write('Plugins=plugins\n')
f.write('Imports=imports\n')
f.write('Qml2Imports=qml\n')
f.write('Libraries={0}\n'.format(os.path.relpath(os.path.join(install_dir, 'lib', 'qtcreator'), target_dir).replace('\\', '/')))
f.write('Plugins={0}\n'.format(os.path.relpath(os.path.join(install_dir, 'bin', 'plugins'), target_dir).replace('\\', '/')))
f.write('Imports={0}\n'.format(os.path.relpath(os.path.join(install_dir, 'bin', 'imports'), target_dir).replace('\\', '/')))
f.write('Qml2Imports={0}\n'.format(os.path.relpath(os.path.join(install_dir, 'bin', 'qml'), target_dir).replace('\\', '/')))
f.close()
def copy_translations(install_dir, qt_tr_dir):
@@ -231,12 +196,14 @@ def copyPreservingLinks(source, destination):
else:
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)
deployinfo = []
if sys.platform.startswith("win"):
if common.is_windows_platform():
deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'libclang.dll'),
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'),
os.path.join(install_dir, 'bin')))
else:
@@ -259,14 +226,20 @@ def copy_libclang(install_dir, llvm_install_dir):
for source, target in deployinfo:
print 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
if (os.path.exists(resourcetarget)):
shutil.rmtree(resourcetarget)
shutil.copytree(resourcesource, resourcetarget, symlinks=True)
def readQmakeVar(qmake_bin, var):
pipe = os.popen(' '.join([qmake_bin, '-query', var]))
return pipe.read().rstrip('\n')
common.copytree(resourcesource, resourcetarget, symlinks=True)
def main():
try:
@@ -298,40 +271,45 @@ def main():
print "Cannot find required binary 'qmake'."
sys.exit(2)
if not sys.platform.startswith('win'):
chrpath_bin = None
if common.is_linux_platform():
chrpath_bin = which('chrpath')
if chrpath_bin == None:
print "Cannot find required binary 'chrpath'."
sys.exit(2)
QT_INSTALL_LIBS = readQmakeVar(qmake_bin, 'QT_INSTALL_LIBS')
QT_INSTALL_BINS = readQmakeVar(qmake_bin, 'QT_INSTALL_BINS')
QT_INSTALL_PLUGINS = readQmakeVar(qmake_bin, 'QT_INSTALL_PLUGINS')
QT_INSTALL_IMPORTS = readQmakeVar(qmake_bin, 'QT_INSTALL_IMPORTS')
QT_INSTALL_QML = readQmakeVar(qmake_bin, 'QT_INSTALL_QML')
QT_INSTALL_TRANSLATIONS = readQmakeVar(qmake_bin, 'QT_INSTALL_TRANSLATIONS')
qt_install_info = common.get_qt_install_info(qmake_bin)
QT_INSTALL_LIBS = qt_install_info['QT_INSTALL_LIBS']
QT_INSTALL_BINS = qt_install_info['QT_INSTALL_BINS']
QT_INSTALL_PLUGINS = qt_install_info['QT_INSTALL_PLUGINS']
QT_INSTALL_IMPORTS = qt_install_info['QT_INSTALL_IMPORTS']
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']
imports = ['Qt', 'QtWebKit']
if sys.platform.startswith('win'):
if common.is_windows_platform():
global debug_build
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)
else:
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)
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'):
fix_rpaths(chrpath_bin, install_dir)
add_qt_conf(install_dir)
if not common.is_windows_platform():
print "fixing rpaths..."
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 sys.platform == 'darwin':
if common.is_mac_platform():
print "Mac OS is not supported by this script, please use macqtdeploy!"
sys.exit(2)
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
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
# check for known existing translation to avoid copying multiple times
if [ ! -f "$1/Contents/Resources/translations/qt_de.qm" ]; then
@@ -82,7 +88,7 @@ fi
if [ ! -d "$1/Contents/Frameworks/QtCore.framework" ]; then
qml2puppetapp="$1/Contents/Resources/qml2puppet"
qml2puppetapp="$1/Contents/Resources/qmldesigner/qml2puppet"
if [ -f "$qml2puppetapp" ]; then
qml2puppetArgument="-executable=$qml2puppetapp"
fi

View File

@@ -38,7 +38,7 @@ import shutil
import inspect
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):
with open(infile, 'r') as f:
@@ -53,7 +53,7 @@ def ifw_template_dir():
def main():
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:
usage()
sys.exit(2)
@@ -64,7 +64,8 @@ def main():
version = ''
ifw_location = ''
archive = ''
archives = []
debug = False
for o, a in opts:
if o in ('-h', '--help'):
usage()
@@ -74,7 +75,9 @@ def main():
if o in ('-i', '--installer-path'):
ifw_location = a
if o in ('-a', '--archive'):
archive = a
archives.append(a)
if o in ('-d', '--debug'):
debug = True
if (version == ''):
raise Exception('Version not specified (--version-string)!')
@@ -82,8 +85,8 @@ def main():
if (ifw_location == ''):
raise Exception('Installer framework location not specified (--installer-path)!')
if (archive == ''):
raise Exception('Archive not specified (--archive)!')
if not archives:
raise ValueError('No archive(s) specified (--archive)!')
installer_name = args[0]
config_postfix = ''
@@ -100,12 +103,15 @@ def main():
try:
temp_dir = tempfile.mkdtemp()
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:
substs = {}
substs['version'] = version
substs['date'] = datetime.date.today().isoformat()
substs['archives'] = ','.join(archives)
template_dir = ifw_template_dir()
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')
if not os.path.exists(data_path):
os.makedirs(data_path)
for archive in archives:
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' ]
if debug:
ifw_call.append('-v')
subprocess.check_call(ifw_call, stderr=subprocess.STDOUT)
finally:
if not debug:
print('Cleaning up...')
shutil.rmtree(temp_dir)
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",
]
self.interpreterSeq = 0
def resetCaches(self):
# This is a cache mapping from 'type name' to 'display alternatives'.
@@ -601,9 +599,6 @@ class DumperBase:
data = self.extractBlob(addr, size).toBytes()
return self.hexencode(data)
def readJsonFromMemory(self, addr, size):
return json.loads(self.hexdecode(self.readMemory(addr, size)))
def encodeByteArray(self, value, limit = 0):
elided, data = self.encodeByteArrayHelper(self.extractPointer(value), limit)
return data
@@ -834,16 +829,99 @@ class DumperBase:
self.putSpecialValue(SpecialItemCountValue, count)
self.putNumChild(count)
def dictToMi(self, value):
def resultToMi(self, value):
if type(value) is bool:
return '"%d"' % int(value)
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())]) + '}'
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
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):
self.put('%s="%s",' % (name, value))
@@ -1753,34 +1831,86 @@ class DumperBase:
value = struct.unpack_from("!I", buf, offset)[0]
return (value, offset + 4)
def readInterpreterOutput(self):
buf = self.parseAndEvaluate("qt_qmlDebugOutputBuffer")
size = self.parseAndEvaluate("qt_qmlDebugOutputLength")
return self.readJsonFromMemory(buf, size)
def handleInterpreterEvent(self):
def handleInterpreterMessage(self):
""" Return True if inferior stopped """
buf = self.parseAndEvaluate("qt_qmlDebugEventBuffer")
size = self.parseAndEvaluate("qt_qmlDebugEventLength")
resdict = self.readJsonFromMemory(buf, size)
warn("RES DICT : %s" % resdict)
resdict = self.fetchInterpreterResult()
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):
res = self.sendInterpreterRequest('removebreakpoint', { 'id' : args['id'] })
return res
def insertInterpreterBreakpoint(self, args):
args['condition'] = self.hexdecode(args.get('condition', ''))
warn("Insert interpreter breakpoint %s:%s (%s)"
% (args['file'], args['line'], args['condition']))
bp = self.doInsertInterpreterBreakpoint(args, False)
return str(bp)
# Will fail if the service is not yet up and running.
response = self.sendInterpreterRequest('setbreakpoint', args)
resdict = args.copy()
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 = {}):
self.interpreterSeq += 1
cmd = { 'seq': self.interpreterSeq, 'type': 'request', 'command': command, 'arguments': args }
encoded = json.dumps(cmd)
encoded = json.dumps({ 'command': command, 'arguments': args })
hexdata = self.hexencode(encoded)
expr = 'qt_qmlDebugSendDataToService("NativeQmlDebugger","%s")' % hexdata
try:
@@ -1792,21 +1922,10 @@ class DumperBase:
# Happens with LLDB and 'None' current thread.
warn("Interpreter command failed: %s: %s" % (encoded, error))
return {}
if not res:
warn("Interpreter command failed: %s " % encoded)
return {}
resdict = self.readInterpreterOutput()
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 }
return self.fetchInterpreterResult()
def executeStep(self, args):
if self.nativeMixed:
@@ -1829,23 +1948,22 @@ class DumperBase:
self.doContinue()
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.
response = self.sendInterpreterRequest('setbreakpoint', args)
bp = None if response is None else response.get("breakpoint", None)
if wasPending:
if not bp:
warn("ERROR: Pending interpreter breakpoint insertion failed.")
return -1
self.reportInterpreterResult({'bpnr': -1, 'pending': 1,
'error': 'Pending interpreter breakpoint insertion failed.'}, args)
return
else:
if not bp:
warn("Direct interpreter breakpoint insertion failed.")
warn("Make pending.")
self.reportInterpreterResult({'bpnr': -1, 'pending': 1,
'warning': 'Direct interpreter breakpoint insertion failed.'}, args)
self.createResolvePendingBreakpointsHookBreakpoint(args)
return -1
warn("Resolved interpreter breakpoint: BP: %s" % bp)
return int(bp)
return
self.reportInterpreterResult({'bpnr': bp, 'pending': 0}, args)
def isInternalInterpreterFrame(self, functionName):
if functionName is None:
@@ -1875,6 +1993,11 @@ class DumperBase:
def extractInterpreterStack(self):
return self.sendInterpreterRequest('backtrace', {'limit': 10 })
def extractInterpreterVariables(self, args):
return self.sendInterpreterRequest('variables', args)
def polishWatchers(self, watchers):
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'.
self.isGdb = True
self.childEventAddress = None
self.typeCache = {}
self.typesReported = {}
self.typesToReport = {}
self.qtNamespaceToReport = None
self.interpreterBreakpoints = []
self.interpreterBreakpointResolvers = []
def prepare(self, args):
self.output = []
@@ -359,12 +358,9 @@ class Dumper(DumperBase):
partialVariable = args.get("partialVariable", "")
isPartial = len(partialVariable) > 0
if self.nativeMixed:
context = args.get('context', '')
if len(context):
res = self.extractInterpreterVariables(args)
if res:
safePrint('data=%s' % self.dictToMi(res.get('data', {})))
(ok, res) = self.tryFetchInterpreterVariables(args)
if ok:
safePrint(res)
return
#
@@ -1607,7 +1603,7 @@ class Dumper(DumperBase):
objfile = fromNativePath(symtab.objfile.filename)
fileName = fromNativePath(symtab.fullname())
if self.nativeMixed and functionName == "qt_qmlDebugEventFromService":
if self.nativeMixed and functionName == "qt_qmlDebugMessageAvailable":
interpreterStack = self.extractInterpreterStack()
#print("EXTRACTED INTEPRETER STACK: %s" % interpreterStack)
for interpreterFrame in interpreterStack.get('frames', []):
@@ -1645,17 +1641,15 @@ class Dumper(DumperBase):
self.dumper = dumper
self.args = args
spec = "qt_qmlDebugConnectorOpen"
print("Preparing hook to resolve pending QML breakpoint at %s" % args)
super(Resolver, self).\
__init__(spec, gdb.BP_BREAKPOINT, internal=True, temporary=False)
def stop(self):
bp = self.dumper.doInsertInterpreterBreakpoint(args, True)
print("Resolving QML breakpoint %s -> %s" % (args, bp))
self.dumper.resolvePendingInterpreterBreakpoint(args)
self.enabled = False
return False
self.interpreterBreakpoints.append(Resolver(self, args))
self.interpreterBreakpointResolvers.append(Resolver(self, args))
def exitGdb(self, _):
gdb.execute("quit")
@@ -1804,26 +1798,14 @@ registerCommand("threadnames", threadnames)
#
#######################################################################
class TriggeredBreakpointHookBreakpoint(gdb.Breakpoint):
class InterpreterMessageBreakpoint(gdb.Breakpoint):
def __init__(self):
spec = "qt_v4TriggeredBreakpointHook"
super(TriggeredBreakpointHookBreakpoint, self).\
spec = "qt_qmlDebugMessageAvailable"
super(InterpreterMessageBreakpoint, self).\
__init__(spec, gdb.BP_BREAKPOINT, internal=True)
def stop(self):
print("QML engine stopped.")
return True
print("Interpreter event received.")
return theDumper.handleInterpreterMessage()
TriggeredBreakpointHookBreakpoint()
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()
InterpreterMessageBreakpoint()

View File

@@ -48,9 +48,6 @@ from dumper import *
qqWatchpointOffset = 10000
def warn(message):
print('\n\nWARNING="%s",\n' % message.encode("latin1").replace('"', "'"))
def showException(msg, exType, exValue, exTraceback):
warn("**** CAUGHT EXCEPTION: %s ****" % msg)
import traceback
@@ -230,8 +227,7 @@ class Dumper(DumperBase):
self.voidPtrType_ = None
self.isShuttingDown_ = False
self.isInterrupting_ = False
self.qmlBreakpointResolvers = {}
self.qmlTriggeredBreakpoint = None
self.interpreterBreakpointResolvers = []
self.report('lldbversion=\"%s\"' % lldb.SBDebugger.GetVersionString())
self.reportState("enginesetupok")
@@ -549,7 +545,7 @@ class Dumper(DumperBase):
self.report('error="%s"' % result.GetError())
def put(self, stuff):
self.out += stuff
self.output += stuff
def isMovableType(self, type):
if type.GetTypeClass() in (lldb.eTypeClassBuiltin, lldb.eTypeClassPointer):
@@ -667,6 +663,7 @@ class Dumper(DumperBase):
self.sysRoot_ = args.get('sysRoot', '')
self.remoteChannel_ = args.get('remoteChannel', '')
self.platform_ = args.get('platform', '')
self.nativeMixed = int(args.get('nativemixed', 0))
self.ignoreStops = 0
self.silentStops = 0
@@ -689,12 +686,15 @@ class Dumper(DumperBase):
if self.sysRoot_:
self.debugger.SetCurrentPlatformSDKRoot(self.sysRoot_)
if os.path.isfile(self.executable_):
self.target = self.debugger.CreateTarget(self.executable_, None, None, True, error)
else:
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
self.reportResult('success="%s",msg="%s",exe="%s"' % (state, error, self.executable_), args)
@@ -775,9 +775,11 @@ class Dumper(DumperBase):
def describeLocation(self, frame):
if int(frame.pc) == 0xffffffffffffffff:
return ''
file = fileNameAsString(frame.line_entry.file)
fileName = fileNameAsString(frame.line_entry.file)
function = frame.GetFunctionName()
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):
return None if self.process is None else self.process.GetSelectedThread()
@@ -847,8 +849,6 @@ class Dumper(DumperBase):
self.reportResult('msg="No thread"', args)
return
self.report(self.describeLocation(thread.GetFrameAtIndex(0))) # FIXME
isNativeMixed = int(args.get('nativemixed', 0))
limit = args.get('stacklimit', -1)
@@ -868,38 +868,27 @@ class Dumper(DumperBase):
pc = frame.GetPC()
level = frame.idx
addr = frame.GetPCAddress().GetLoadAddress(self.target)
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)
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 += ',level="%d"' % level
result += ',address="0x%x"' % addr
if not usable is None:
result += ',usable="%s"' % usable
result += ',function="%s"' % functionName
result += ',line="%d"' % lineNumber
if not language is None:
result += ',language="%s"' % language
result += ',file="%s"},' % fileName
result += ']'
result += ',hasmore="%d"' % isLimited
@@ -1155,16 +1144,28 @@ class Dumper(DumperBase):
with SubItem(self, child):
self.putItem(child)
def reportVariables(self, args):
self.out = ""
self.reportVariablesHelper(args)
self.reportResult(self.out, args)
def reportVariablesHelper(self, args = {}):
frame = self.currentFrame()
if frame is None:
def fetchVariables(self, args):
(ok, res) = self.tryFetchInterpreterVariables(args)
if ok:
self.reportResult(res, args)
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", "")
isPartial = len(partialVariable) > 0
@@ -1232,6 +1233,7 @@ class Dumper(DumperBase):
self.handleWatches(args)
self.put('],partial="%d"' % isPartial)
self.reportResult(self.output, args)
def fetchRegisters(self, args = None):
if self.process is None:
@@ -1281,7 +1283,7 @@ class Dumper(DumperBase):
else:
self.isInterrupting_ = True
error = self.process.Stop()
self.reportResult(describeError(error), args)
self.reportResult(self.describeError(error), args)
def detachInferior(self, args):
if self.process is None:
@@ -1330,28 +1332,31 @@ class Dumper(DumperBase):
frame = stoppedThread.GetFrameAtIndex(0)
#self.report("FRAME: %s" % frame)
function = frame.GetFunction()
#self.report("FUNCTION: %s" % function)
if function.GetName() == "qt_v4ResolvePendingBreakpointsHook":
#self.report("RESOLVER HIT")
for bp in self.qmlBreakpointResolvers:
self.qmlBreakpointResolvers[bp]()
self.target.BreakpointDelete(bp.GetID())
self.qmlBreakpointResolvers = {}
functionName = function.GetName()
if functionName == "::qt_qmlDebugConnectorOpen()":
self.report("RESOLVER HIT")
for resolver in self.interpreterBreakpointResolvers:
resolver()
self.report("AUTO-CONTINUE AFTER RESOLVING")
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();
return
if self.isInterrupting_:
self.isInterrupting_ = False
self.reportState("inferiorstopok")
self.reportState("stopped")
elif self.ignoreStops > 0:
self.ignoreStops -= 1
self.process.Continue()
elif self.silentStops > 0:
self.silentStops -= 1
#elif bp and bp in self.qmlBreakpointResolvers:
# self.report("RESOLVER HIT")
# self.qmlBreakpointResolvers[bp]()
# self.process.Continue();
else:
self.reportState("stopped")
else:
@@ -1422,7 +1427,7 @@ class Dumper(DumperBase):
if bpType == BreakpointByFileAndLine:
fileName = args["file"]
if fileName.endswith(".js") or fileName.endswith(".qml"):
self.doInsertInterpreterBreakpoint(args, False)
self.insertInterpreterBreakpoint(args)
return
extra = ''
@@ -1645,19 +1650,6 @@ class Dumper(DumperBase):
error = str(result.GetError())
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):
functionName = args.get('function', '')
flavor = args.get('flavor', '')
@@ -1744,17 +1736,13 @@ class Dumper(DumperBase):
value = self.hexdecode(args['value'])
lhs = self.findValueByExpression(exp)
lhs.SetValueFromCString(value, error)
self.reportResult(describeError(error), args)
self.reportResult(self.describeError(error), args)
def createResolvePendingBreakpointsHookBreakpoint(self, args):
if self.qmlTriggeredBreakpoint is None:
self.qmlTriggeredBreakpoint = \
self.target.BreakpointCreateByName("qt_v4TriggeredBreakpointHook")
bp = self.target.BreakpointCreateByName("qt_v4ResolvePendingBreakpointsHook")
bp = self.target.BreakpointCreateByName("qt_qmlDebugConnectorOpen")
bp.SetOneShot(True)
self.qmlBreakpointResolvers[bp] = lambda: \
self.doInsertQmlBreakpoint(args)
self.interpreterBreakpointResolvers.append(
lambda: self.resolvePendingInterpreterBreakpoint(args))
# Used in dumper auto test.
@@ -1825,7 +1813,7 @@ class Tester(Dumper):
if line != 0:
self.report = savedReport
self.process.SetSelectedThread(stoppedThread)
self.reportVariables({'token':2})
self.fetchVariables({'token':2, 'fancy':1})
#self.describeLocation(frame)
self.report("@NS@%s@" % self.qtNamespace())
#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())
def qdump__QV4__Value(d, value):
v = toInteger(str(value["val"]))
v = toInteger(str(value["_val"]))
NaNEncodeMask = 0xffff800000000000
IsInt32Mask = 0x0002000000000000
IsDoubleMask = 0xfffc000000000000
@@ -2319,7 +2319,10 @@ def qdump__QV4__Value(d, value):
ns = d.qtNamespace()
if v & IsInt32Mask:
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:
d.putBetterType("%sQV4::Value (double)" % ns)
d.putValue("%x" % (v ^ 0xffff800000000000), Hex2EncodedFloat8)
@@ -2332,6 +2335,7 @@ def qdump__QV4__Value(d, value):
elif v & IsNullOrBooleanMask:
d.putBetterType("%sQV4::Value (null/bool)" % ns)
d.putValue("(null/bool)")
d.putValue(v & 1)
else:
vtable = value["m"]["vtable"]
if toInteger(vtable["isString"]):

View File

@@ -53,6 +53,129 @@ public:
$$
} else {
}</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>

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 -= gui
CONFIG += c++11
TARGET = %{ProjectName}
CONFIG += console
CONFIG -= app_bundle

View File

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

View File

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

View File

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

View File

@@ -50,6 +50,7 @@ DObject::DObject()
DObject::DObject(const DObject &rhs)
: DElement(rhs),
_model_uid(rhs._model_uid),
_stereotypes(rhs._stereotypes),
_context(rhs._context),
_name(rhs._name),
_pos(rhs._pos),
@@ -72,6 +73,7 @@ DObject &DObject::operator =(const DObject &rhs)
if (this != &rhs) {
DElement::operator=(rhs);
_model_uid = rhs._model_uid;
_stereotypes = rhs._stereotypes;
_context = rhs._context;
_name = rhs._name;
_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->setEditable(true);
_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));
connect(_stereotype_combo_box->lineEdit(), SIGNAL(textEdited(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
if (_reverse_engineered_label == 0) {
_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");
_reverse_engineered_label->setText(text);
@@ -428,7 +428,7 @@ void PropertiesView::MView::visitMObject(const MObject *object)
bool is_single_selection = selection.size() == 1;
if (_element_name_line_edit == 0) {
_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)));
}
if (is_single_selection) {
@@ -445,12 +445,12 @@ void PropertiesView::MView::visitMObject(const MObject *object)
#ifdef SHOW_DEBUG_PROPERTIES
if (_children_label == 0) {
_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()));
if (_relations_label == 0) {
_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()));
#endif
@@ -474,7 +474,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
bool is_single_selection = selection.size() == 1;
if (_namespace_line_edit == 0) {
_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)));
}
if (!_namespace_line_edit->hasFocus()) {
@@ -491,7 +491,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
}
if (_template_parameters_line_edit == 0) {
_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)));
}
if (is_single_selection) {
@@ -525,7 +525,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
if (_class_members_edit == 0) {
_class_members_edit = new ClassMembersEdit(_top_widget);
_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(statusChanged(bool)), this, SLOT(onClassMembersStatusChanged(bool)));
}
@@ -554,7 +554,7 @@ void PropertiesView::MView::visitMDiagram(const MDiagram *diagram)
#ifdef SHOW_DEBUG_PROPERTIES
if (_diagrams_label == 0) {
_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()));
#endif
@@ -575,7 +575,7 @@ void PropertiesView::MView::visitMItem(const MItem *item)
if (item->isVarietyEditable()) {
if (_item_variety_edit == 0) {
_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)));
}
if (is_single_selection) {
@@ -598,7 +598,7 @@ void PropertiesView::MView::visitMRelation(const MRelation *relation)
bool is_single_selection = selection.size() == 1;
if (_element_name_line_edit == 0) {
_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)));
}
if (is_single_selection) {
@@ -628,7 +628,7 @@ void PropertiesView::MView::visitMDependency(const MDependency *dependency)
if (_direction_selector == 0) {
_direction_selector = new QComboBox(_top_widget);
_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)));
}
if (is_single_selection) {
@@ -649,9 +649,9 @@ void PropertiesView::MView::visitMInheritance(const MInheritance *inheritance)
setTitle<MInheritance>(_model_elements, tr("Inheritance"), tr("Inheritances"));
MObject *derived_class = _properties_view->getModelController()->findObject(inheritance->getDerived());
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());
setEndBName(tr("Base Class: %1").arg(base_class->getName()));
setEndBName(tr("Base class: %1").arg(base_class->getName()));
visitMRelation(inheritance);
}
@@ -667,7 +667,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (_end_a_end_name == 0) {
_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)));
}
if (is_single_selection) {
@@ -682,7 +682,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (_end_a_cardinality == 0) {
_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)));
}
if (is_single_selection) {
@@ -713,7 +713,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
if (_end_a_kind == 0) {
_end_a_kind = new QComboBox(_top_widget);
_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)));
}
if (is_single_selection) {
@@ -734,7 +734,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (_end_b_end_name == 0) {
_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)));
}
if (is_single_selection) {
@@ -749,7 +749,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (_end_b_cardinality == 0) {
_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)));
}
if (is_single_selection) {
@@ -780,7 +780,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
if (_end_b_kind == 0) {
_end_b_kind = new QComboBox(_top_widget);
_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)));
}
if (is_single_selection) {
@@ -823,7 +823,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
#ifdef SHOW_DEBUG_PROPERTIES
if (_pos_rect_label == 0) {
_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)"))
.arg(object->getPos().x())
@@ -835,7 +835,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
#endif
if (_auto_sized_checkbox == 0) {
_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)));
}
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_CUSTOM4, 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)));
}
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")
<< tr("Lighter") << tr("Darker")
<< 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)));
}
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->addItems(QStringList() << tr("Smart") << tr("None") << tr("Label")
<< 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)));
}
if (!_stereotype_display_selector->hasFocus()) {
@@ -922,7 +922,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
#ifdef SHOW_DEBUG_PROPERTIES
if (_depth_label == 0) {
_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()));
#endif
@@ -945,7 +945,7 @@ void PropertiesView::MView::visitDClass(const DClass *klass)
if (_template_display_selector == 0) {
_template_display_selector = new QComboBox(_top_widget);
_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)));
}
if (!_template_display_selector->hasFocus()) {
@@ -958,7 +958,7 @@ void PropertiesView::MView::visitDClass(const DClass *klass)
}
if (_show_all_members_checkbox == 0) {
_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)));
}
if (!_show_all_members_checkbox->hasFocus()) {
@@ -979,7 +979,7 @@ void PropertiesView::MView::visitDComponent(const DComponent *component)
visitDObject(component);
if (_plain_shape_checkbox == 0) {
_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)));
}
if (!_plain_shape_checkbox->hasFocus()) {
@@ -1010,7 +1010,7 @@ void PropertiesView::MView::visitDItem(const DItem *item)
if (item->isShapeEditable()) {
if (_item_shape_edit == 0) {
_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)));
}
if (is_single_selection) {
@@ -1055,7 +1055,7 @@ void PropertiesView::MView::visitDAnnotation(const DAnnotation *annotation)
visitDElement(annotation);
if (_annotation_auto_width_checkbox == 0) {
_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)));
}
if (!_annotation_auto_width_checkbox->hasFocus()) {
@@ -1069,7 +1069,7 @@ void PropertiesView::MView::visitDAnnotation(const DAnnotation *annotation)
if (_annotation_visual_role_selector == 0) {
_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"));
_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)));
}
if (!_annotation_visual_role_selector->hasFocus()) {

View File

@@ -125,7 +125,6 @@ HEADERS += \
$$PWD/model_widgets_ui/propertiesviewmview.h \
$$PWD/project_controller/projectcontroller.h \
$$PWD/project/project.h \
$$PWD/serializer/diagramreferenceserializer.h \
$$PWD/serializer/diagramserializer.h \
$$PWD/serializer/infrastructureserializer.h \
$$PWD/serializer/modelserializer.h \
@@ -253,7 +252,6 @@ SOURCES += \
$$PWD/model_widgets_ui/propertiesviewmview.cpp \
$$PWD/project_controller/projectcontroller.cpp \
$$PWD/project/project.cpp \
$$PWD/serializer/diagramreferenceserializer.cpp \
$$PWD/serializer/diagramserializer.cpp \
$$PWD/serializer/infrastructureserializer.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);
}
template<class Archive, class T>
void save(Archive &archive, const T &t, const Parameters &)
{
save(archive, t);
}
template<class Archive, class T>
void load(Archive &archive, T &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>
void serialize(Archive &archive, T &t)
{
@@ -92,30 +104,9 @@ void serialize_helper(Archive &archive, T &t)
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) \
template class Access<INARCHIVE, 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

View File

@@ -33,6 +33,10 @@
#include "flag.h"
#include <QVariant>
#include <QString>
#include <QHash>
namespace qark {
class ArchiveBasics
@@ -48,8 +52,40 @@ public:
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:
Flag::mask_type _flags;
QHash<QString, QVariant> _user_data;
};
}

View File

@@ -31,6 +31,8 @@
#ifndef QARK_ATTRIBUTE_H
#define QARK_ATTRIBUTE_H
#include "parameters.h"
#include <QString>
namespace qark {
@@ -38,19 +40,29 @@ namespace qark {
template<typename T>
class Attr {
public:
explicit Attr(const QString &qualified_name, T *value)
Attr(const QString &qualified_name, T *value)
: _qualified_name(qualified_name),
_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; }
T *getValue() const { return _value; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
T *_value;
Parameters _parameters;
};
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);
}
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>
Attr<T> attr(const QString &qualified_name, T &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>
class GetterAttr {
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),
_u(u),
_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 U &getObject() const { return _u; }
T (U::*getGetter() const)() const { return _getter; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
const U &_u;
T (U::*_getter)() const;
Parameters _parameters;
};
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);
}
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>
class SetterAttr {
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),
_u(u),
_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; }
U &getObject() const { return _u; }
void (U::*getSetter() const)(T) { return _setter; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
U &_u;
void (U::*_setter)(T);
Parameters _parameters;
};
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);
}
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>
class GetterSetterAttr {
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),
_u(u),
_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; }
U &getObject() const { return _u; }
@@ -143,11 +210,14 @@ public:
void (U::*getSetter() const)(V) { return _setter; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
U &_u;
T (U::*_getter)() const;
void (U::*_setter)(V);
Parameters _parameters;
};
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);
}
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>
class GetFuncAttr {
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),
_u(u),
_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; }
U &getObject() const { return _u; }
T (*getGetFunc() const)(const U &) { return _get_func; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
U &_u;
T (*_get_func)(const U &);
Parameters _parameters;
};
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);
}
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>
class SetFuncAttr {
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),
_u(u),
_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; }
U &getObject() const { return _u; }
void (*getSetFunc() const)(U &, T) { return _set_func; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
U &_u;
void (*_set_func)(U &, T);
Parameters _parameters;
};
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);
}
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>
class GetSetFuncAttr {
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),
_u(u),
_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; }
U &getObject() const { return _u; }
@@ -234,11 +353,14 @@ public:
void (*getSetFunc() const)(U &, V) { return _set_func; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
U &_u;
T (*_get_func)(const U &);
void (*_set_func)(U &, V);
Parameters _parameters;
};
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);
}
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

View File

@@ -32,6 +32,7 @@
#define QARK_BASECLASS_H
#include "typeregistry.h"
#include "parameters.h"
#include <QString>
@@ -41,21 +42,31 @@ namespace qark {
template<class BASE, class DERIVED>
class Base {
public:
explicit Base(const QString &qualified_name, DERIVED &obj)
Base(const QString &qualified_name, DERIVED &obj)
: _qualified_name(qualified_name),
_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 BASE &getBase() const { return _base; }
BASE &getBase() { return _base; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
BASE &_base;
Parameters _parameters;
};
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);
}
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>
Base<BASE, DERIVED> base(const QString &qualified_name, DERIVED *&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>
Base<BASE, DERIVED> base(DERIVED &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

View File

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

View File

@@ -28,59 +28,44 @@
**
****************************************************************************/
#ifndef QMT_DIAGRAMREFERENCESERIALIZER_H
#define QMT_DIAGRAMREFERENCESERIALIZER_H
#ifndef QARK_PARAMETER_H
#define QARK_PARAMETER_H
#include "qmt/infrastructure/uid.h"
#include "flag.h"
#include <QString>
namespace qark {
QT_BEGIN_NAMESPACE
class QXmlStreamReader;
class QXmlStreamWriter;
QT_END_NAMESPACE
namespace qmt {
class Project;
class MDiagram;
class QMT_EXPORT DiagramReferenceSerializer
class Parameters
{
public:
struct Reference {
Reference();
Reference(const Uid &model_uid, const Uid &diagram_uid);
Uid _model_uid;
Uid _diagram_uid;
};
public:
DiagramReferenceSerializer();
~DiagramReferenceSerializer();
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:
void write(const Reference &reference, QXmlStreamWriter *writer);
Reference read(QXmlStreamReader *stream_reader);
Flag::mask_type _flags;
};
}
#endif // QMT_DIAGRAMREFERENCESERIALIZER_H
#endif // QARK_PARAMETER_H

View File

@@ -75,7 +75,7 @@ private:
typedef QList<Node *> children_type;
public:
virtual ~Node() { }
virtual ~Node() { qDeleteAll(_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 acceptForwardRef(QXmlInArchive &visitor, const impl::ObjectId &id) { visitor.visitForwardRef(this, id); }
void append(Node *node) { _children.push_back(node); }
private:
@@ -237,8 +235,6 @@ private:
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; }
private:
@@ -256,8 +252,6 @@ private:
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; }
private:
@@ -275,8 +269,6 @@ private:
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; }
private:
@@ -294,8 +286,6 @@ private:
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; }
private:
@@ -313,35 +303,23 @@ private:
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; }
private:
GetSetFuncRef<U, T, V> _ref;
};
struct ForwardReference {
ForwardReference(Node *node, const impl::ObjectId &id) : _node(node), _id(id) { }
Node *_node;
impl::ObjectId _id;
};
public:
explicit QXmlInArchive(QXmlStreamReader &stream)
: _stream(stream),
_end_tag_was_read(false),
_root_node(0),
_current_ref_node(0)
{
}
~QXmlInArchive()
{
foreach(const ForwardReference &forward_ref, _forward_references) {
forward_ref._node->acceptForwardRef(*this, forward_ref._id);
}
}
public:
@@ -387,9 +365,7 @@ public:
void append(const Tag &tag)
{
TagNode *node = new TagNode(tag);
if (_node_stack.empty()) {
_root_node = node;
} else {
if (!_node_stack.empty()) {
_node_stack.top()->append(node);
}
_node_stack.push(node);
@@ -399,9 +375,7 @@ public:
void append(const Object<T> &object)
{
ObjectNode<T> *node = new ObjectNode<T>(object);
if (_node_stack.empty()) {
_root_node = node;
} else {
if (!_node_stack.empty()) {
_node_stack.top()->append(node);
}
_node_stack.push(node);
@@ -409,13 +383,14 @@ public:
void append(const End &)
{
_node_stack.pop();
Node *node = _node_stack.pop();
if (_node_stack.empty()) {
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();
}
_root_node->accept(*this, xml_tag);
node->accept(*this, xml_tag);
delete node;
}
}
@@ -587,13 +562,8 @@ public:
if (_loading_ref_map.hasObject(id)) {
p = _loading_ref_map.getObject<T *>(id);
} else {
if (_current_ref_node == 0) {
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:
@@ -634,11 +604,6 @@ private:
throw FileFormatException();
}
void visitForwardRef(Node *, const impl::ObjectId &)
{
throw UnexpectedForwardReference();
}
void visit(TagNode *node, const XmlTag &)
{
readChildren(node);
@@ -656,7 +621,7 @@ private:
template<class T, class U>
void visit(BaseNode<T, U> *node, const XmlTag &)
{
(*this) >> node->getBase().getBase();
load(*this, node->getBase().getBase(), node->getBase().getParameters());
XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getBase().getQualifiedName()) {
throw FileFormatException();
@@ -666,7 +631,7 @@ private:
template<class T>
void visit(AttrNode<T> *node, const XmlTag &)
{
(*this) >> *node->getAttribute().getValue();
load(*this, *node->getAttribute().getValue(), node->getAttribute().getParameters());
XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
throw FileFormatException();
@@ -677,7 +642,7 @@ private:
void visit(SetterAttrNode<U, T> *node, const XmlTag &)
{
T value;
(*this) >> value;
load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value);
XmlTag xml_tag = readTag();
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 &)
{
T value;
(*this) >> value;
load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value);
XmlTag xml_tag = readTag();
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 &)
{
V value;
(*this) >> value;
load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value);
XmlTag xml_tag = readTag();
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 &)
{
V value;
(*this) >> value;
load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getObject().*(node->getAttribute().getSetter()))(value);
XmlTag xml_tag = readTag();
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 &)
{
T value;
(*this) >> value;
load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value);
XmlTag xml_tag = readTag();
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 &)
{
T value;
(*this) >> value;
load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value);
XmlTag xml_tag = readTag();
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 &)
{
V value;
(*this) >> value;
load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value);
XmlTag xml_tag = readTag();
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 &)
{
V value;
(*this) >> value;
load(*this, value, node->getAttribute().getParameters());
(node->getAttribute().getSetFunc())(node->getAttribute().getObject(), value);
XmlTag xml_tag = readTag();
if (!xml_tag._end_tag || xml_tag._tag_name != node->getAttribute().getQualifiedName()) {
@@ -774,8 +739,8 @@ private:
{
_current_ref_node = node;
T value = T();
(*this) >> value;
if (_current_ref_node != 0) { // ref node was not eaten by forward reference
load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not consumed by forward reference
*node->getReference().getValue() = value;
_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>
void visit(SetterRefNode<U, T> *node, const XmlTag &)
{
_current_ref_node = node;
T value;
(*this) >> value;
if (_current_ref_node != 0) { // ref node was not eaten by forward reference
load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
_current_ref_node = 0;
}
@@ -816,8 +771,8 @@ private:
{
_current_ref_node = node;
T value;
(*this) >> value;
if (_current_ref_node != 0) { // ref node was not eaten by forward reference
load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
_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>
void visit(GetterSetterRefNode<U, T, V> *node, const XmlTag &)
{
_current_ref_node = node;
V value;
(*this) >> value;
if (_current_ref_node != 0) { // ref node was not eaten by forward reference
load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
_current_ref_node = 0;
}
@@ -868,8 +803,8 @@ private:
{
_current_ref_node = node;
V value;
(*this) >> value;
if (_current_ref_node != 0) { // ref node was not eaten by forward reference
load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
_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>
void visit(SetFuncRefNode<U, T> *node, const XmlTag &)
{
_current_ref_node = node;
T value;
(*this) >> value;
if (_current_ref_node != 0) { // ref node was not eaten by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getSetFunc())(node->getReference().getObject(), value);
_current_ref_node = 0;
}
XmlTag xml_tag = readTag();
@@ -920,9 +835,9 @@ private:
{
_current_ref_node = node;
T value;
(*this) >> value;
if (_current_ref_node != 0) { // ref node was not eaten by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getSetFunc())(node->getReference().getObject(), value);
_current_ref_node = 0;
}
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>
void visit(GetSetFuncRefNode<U, T, V> *node, const XmlTag &)
{
_current_ref_node = node;
V value;
(*this) >> value;
if (_current_ref_node != 0) { // ref node was not eaten by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getSetFunc())(node->getReference().getObject(), value);
_current_ref_node = 0;
}
XmlTag xml_tag = readTag();
@@ -972,9 +867,9 @@ private:
{
_current_ref_node = node;
V value;
(*this) >> value;
if (_current_ref_node != 0) { // ref node was not eaten by forward reference
(node->getReference().getObject().*(node->getReference().getSetter()))(value);
load(*this, value, node->getReference().getParameters());
if (_current_ref_node != 0) { // ref node was not consumed by forward reference
(node->getReference().getSetFunc())(node->getReference().getObject(), value);
_current_ref_node = 0;
}
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:
inline XmlTag readTag();
@@ -1012,11 +887,9 @@ private:
private:
QXmlStreamReader &_stream;
bool _end_tag_was_read;
Node *_root_node;
QStack<Node *> _node_stack;
impl::LoadingRefMap _loading_ref_map;
Node *_current_ref_node;
QList<ForwardReference> _forward_references;
};

View File

@@ -49,6 +49,11 @@ class QXmlOutArchive :
{
public:
class UnsupportedForwardReference :
public std::exception
{
};
class DanglingReferences :
public std::exception
{
@@ -58,6 +63,7 @@ public:
static const bool out_archive = true;
public:
QXmlOutArchive(QXmlStreamWriter &stream)
: _stream(stream),
_next_pointer_is_reference(false)
@@ -76,6 +82,9 @@ public:
template<typename T>
void write(T *p)
{
if (!_saving_ref_map.hasDefinedRef(p)) {
throw UnsupportedForwardReference();
}
write(_saving_ref_map.getRef(p).get());
}
@@ -132,7 +141,12 @@ public:
void beginElement(const Object<T> &object)
{
_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 &)

View File

@@ -31,6 +31,8 @@
#ifndef QARK_REFERENCE_H
#define QARK_REFERENCE_H
#include "parameters.h"
#include <QString>
namespace qark {
@@ -38,19 +40,29 @@ namespace qark {
template<typename T>
class Ref {
public:
explicit Ref(const QString &qualified_name, T *value)
Ref(const QString &qualified_name, T *value)
: _qualified_name(qualified_name),
_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; }
T *getValue() const { return _value; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
T *_value;
Parameters _parameters;
};
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);
}
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>
Ref<T *> ref(const QString &qualified_name, T *&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>
class GetterRef {
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),
_u(u),
_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 U &getObject() const { return _u; }
T (U::*getGetter() const)() const { return _getter; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
const U &_u;
T (U::*_getter)() const;
Parameters _parameters;
};
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);
}
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>
class SetterRef {
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),
_u(u),
_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; }
U &getObject() const { return _u; }
void (U::*getSetter() const)(T) { return _setter; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
U &_u;
void (U::*_setter)(T);
Parameters _parameters;
};
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);
}
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>
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);
}
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>
class GetterSetterRef {
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),
_u(u),
_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; }
U &getObject() const { return _u; }
@@ -147,11 +222,14 @@ public:
void (U::*getSetter() const)(V) { return _setter; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
U &_u;
T (U::*_getter)() const;
void (U::*_setter)(V);
Parameters _parameters;
};
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);
}
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>
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);
}
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>
class GetFuncRef {
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),
_u(u),
_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 U &getObject() const { return _u; }
T (*getGetFunc() const)(const U &) { return _get_func; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
const U &_u;
T (*_get_func)(const U &);
Parameters _parameters;
};
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);
}
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>
class SetFuncRef {
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),
_u(u),
_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; }
U &getObject() const { return _u; }
void (*getSetFunc() const)(U &, T) { return _set_func; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
U &_u;
void (*_set_func)(U &, T);
Parameters _parameters;
};
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);
}
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>
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);
}
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>
class GetSetFuncRef {
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),
_u(u),
_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; }
U &getObject() const { return _u; }
@@ -248,11 +389,14 @@ public:
void (*getSetFunc() const)(U &, V) { return _set_func; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
U &_u;
T (*_get_func)(const U &);
void (*_set_func)(U &, V);
Parameters _parameters;
};
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);
}
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>
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);
}
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

View File

@@ -38,6 +38,7 @@
#include "access.h"
#include "typeregistry.h"
#include "serialize_pointer.h"
#include "serialize_basic.h"
#include "serialize_container.h"
#include "serialize_enum.h"
@@ -51,102 +52,27 @@ namespace qark {
template<class Archive, class T>
inline Archive &operator<<(Archive &archive, const T &t)
{
save(archive, t);
save(archive, t, Parameters());
return archive;
}
template<class Archive, class T>
inline Archive &operator>>(Archive &archive, T &t)
{
load(archive, t);
load(archive, t, Parameters());
return archive;
}
template<class Archive, class T>
typename std::enable_if<Archive::out_archive, Archive &>::type operator||(Archive &archive, T &t)
{
save(archive, (const T &) t);
return archive;
return archive << t;
}
template<class Archive, class T>
typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive &archive, T &t)
{
load(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;
return archive >> t;
}
template<class Archive, class T>
@@ -175,32 +101,6 @@ typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive
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>
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.beginAttribute(attr);
archive << *attr.getValue();
save(archive, *attr.getValue(), attr.getParameters());
archive.endAttribute(attr);
return archive;
}
@@ -336,10 +236,23 @@ typename std::enable_if<Archive::in_archive, Archive &>::type operator||(Archive
}
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 << (attr.getObject().*(attr.getGetter()))();
save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr);
return archive;
}
@@ -358,7 +271,7 @@ operator<<(Archive &archive, const GetterSetterAttr<U, T, V> &attr)
{
if (!((attr.getObject().*(attr.getGetter()))() == (U().*(attr.getGetter()))())) {
archive.beginAttribute(attr);
archive << (attr.getObject().*(attr.getGetter()))();
save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr);
}
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)
{
archive.beginAttribute(attr);
archive << (attr.getObject().*(attr.getGetter()))();
save(archive, (attr.getObject().*(attr.getGetter()))(), attr.getParameters());
archive.endAttribute(attr);
return archive;
}
@@ -398,7 +311,7 @@ template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetFuncAttr<U, T> &attr)
{
archive.beginAttribute(attr);
archive << ((*attr.getGetFunc())(attr.getObject()));
save(archive, ((*attr.getGetFunc())(attr.getObject())), attr.getParameters());
archive.endAttribute(attr);
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.beginAttribute(attr);
archive << ((*attr.getGetFunc())(attr.getObject()));
save(archive, ((*attr.getGetFunc())(attr.getObject())), attr.getParameters());
archive.endAttribute(attr);
return archive;
}
@@ -442,7 +355,7 @@ template<class Archive, typename T>
Archive &operator<<(Archive &archive, const Ref<T *> &ref)
{
archive.beginReference(ref);
archive << *ref.getValue();
save(archive, *ref.getValue(), ref.getParameters());
archive.endReference(ref);
return archive;
}
@@ -451,7 +364,7 @@ template<class Archive, typename T>
Archive &operator<<(Archive &archive, const Ref<T * const> &ref)
{
archive.beginReference(ref);
archive << *ref.getValue();
save(archive, *ref.getValue(), ref.getParameters());
archive.endReference(ref);
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)
{
archive.beginReference(ref);
archive << *ref.getValue();
save(archive, *ref.getValue(), ref.getParameters());
archive.endReference(ref);
return archive;
}
@@ -482,7 +395,7 @@ template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetterRef<U, T> &ref)
{
archive.beginReference(ref);
archive << (ref.getObject().*(ref.getGetter()))();
save(archive, (ref.getObject().*(ref.getGetter()))(), ref.getParameters());
archive.endReference(ref);
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.beginReference(ref);
archive << (ref.getObject().*(ref.getGetter()))();
save(archive, (ref.getObject().*(ref.getGetter()))(), ref.getParameters());
archive.endReference(ref);
return archive;
}
@@ -526,7 +439,7 @@ template<class Archive, class U, typename T>
Archive &operator<<(Archive &archive, const GetFuncRef<U, T> &ref)
{
archive.beginReference(ref);
archive << ref.getGetFunc()(ref.getObject());
save(archive, ref.getGetFunc()(ref.getObject()), ref.getParameters());
archive.endReference(ref);
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.beginReference(ref);
archive << ref.getGetFunc()(ref.getObject());
save(archive, ref.getGetFunc()(ref.getObject()), ref.getParameters());
archive.endReference(ref);
return archive;
}

View File

@@ -31,6 +31,7 @@
#ifndef QARK_SERIALIZE_BASIC_H
#define QARK_SERIALIZE_BASIC_H
#include "parameters.h"
#include "qstringparser/qstringparser.h"
#include <QString>
@@ -42,12 +43,12 @@
#define QARK_BASIC_SAVELOAD(TYPE) \
template<class Archive> \
inline void save(Archive &archive, TYPE v) \
inline void save(Archive &archive, TYPE v, const Parameters &) \
{ \
archive.write(v); \
} \
template<class Archive> \
inline void load(Archive &archive, TYPE &v) \
inline void load(Archive &archive, TYPE &v, const Parameters &) \
{ \
archive.read(&v); \
}
@@ -79,13 +80,13 @@ QARK_BASIC_SAVELOAD(QString)
// QPointF
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()));
}
template<class Archive>
inline void load(Archive &archive, QPointF &point)
inline void load(Archive &archive, QPointF &point, const Parameters &)
{
QString s;
archive.read(&s);
@@ -98,13 +99,13 @@ inline void load(Archive &archive, QPointF &point)
// QRectF
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()));
}
template<class Archive>
inline void load(Archive &archive, QRectF &point)
inline void load(Archive &archive, QRectF &point, const Parameters &)
{
QString s;
archive.read(&s);
@@ -117,13 +118,13 @@ inline void load(Archive &archive, QRectF &point)
// QDateTime
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();
}
template<class Archive>
inline void load(Archive &archive, QDateTime &date_time)
inline void load(Archive &archive, QDateTime &date_time, const Parameters &)
{
qint64 t;
archive >> t;

View File

@@ -31,31 +31,22 @@
#ifndef QARK_SERIALIZE_CONTAINER_H
#define QARK_SERIALIZE_CONTAINER_H
#include "flag.h"
#include "parameters.h"
#include <QList>
#include <QHash>
namespace qark {
namespace impl {
static Flag container_item_ref_flag;
}
template<class Archive>
inline void ref_item(Archive &archive)
{
archive.setFlag(impl::container_item_ref_flag);
}
static Flag ENFORCE_REFERENCED_ITEMS;
// QList
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.clearFlag(impl::container_item_ref_flag);
foreach (const T &t, list) {
archive << attr(QStringLiteral("item"), t);
}
@@ -63,10 +54,10 @@ inline void save(Archive &archive, const QList<T> &list)
}
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");
if (archive.takeFlag(impl::container_item_ref_flag)) {
if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
foreach (const T *t, list) {
archive << ref(QStringLiteral("item"), t);
}
@@ -79,7 +70,7 @@ inline void save(Archive &archive, const QList<T *> &list)
}
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 >> 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>
inline void load(Archive &archive, QList<T *> &list)
inline void load(Archive &archive, QList<T *> &list, const Parameters &parameters)
{
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?
//archive >> ref<QList<T *>, T * const &>("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
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.clearFlag(impl::container_item_ref_flag);
foreach (const T &t, set) {
archive << attr(QStringLiteral("item"), t);
}
@@ -115,10 +105,10 @@ inline void save(Archive &archive, const QSet<T> &set)
}
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");
if (archive.takeFlag(impl::container_item_ref_flag)) {
if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
foreach (const T *t, set) {
archive << ref(QStringLiteral("item"), t);
}
@@ -140,7 +130,7 @@ void insertIntoSet(QSet<T> &set, const T &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 >> 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>
inline void load(Archive &archive, QSet<T *> &set)
inline void load(Archive &archive, QSet<T *> &set, const Parameters &parameters)
{
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 *>);
} else {
archive >> attr<QSet<T *>, T * const &>(QStringLiteral("item"), set, &impl::insertIntoSet<T *>);
@@ -177,7 +167,7 @@ public:
}
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"))
<< 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>
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"))
>> 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>
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"));
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>
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 >> attr(QStringLiteral("item"), hash, &impl::keyValuePairInsert<KEY, VALUE>);

View File

@@ -31,6 +31,8 @@
#ifndef QARK_SERIALIZE_ENUM_H
#define QARK_SERIALIZE_ENUM_H
#include "parameters.h"
#include <type_traits>
namespace qark {
@@ -38,13 +40,13 @@ namespace qark {
#if 0 // ambigous with default implementation in access.h
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);
}
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;
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) \
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); \
} \
template<class Archive> \
inline void load(Archive &archive, ENUM &e) \
inline void load(Archive &archive, ENUM &e, const Parameters &) \
{ \
int i = 0; \
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>
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);
}
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;
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
#include "typeregistry.h"
#include "parameters.h"
#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; }
Parameters getParameters() const { return _parameters; }
private:
QString _qualified_name;
Parameters _parameters;
};
@@ -57,12 +67,18 @@ class Object :
public Tag
{
public:
explicit Object(const QString &qualified_name, T *object)
Object(const QString &qualified_name, T *object)
: Tag(qualified_name),
_object(object)
{
}
Object(const QString &qualified_name, T *object, const Parameters &parameters)
: Tag(qualified_name, parameters),
_object(object)
{
}
T *getObject() const { return _object; }
private:
@@ -75,28 +91,61 @@ inline Tag tag(const QString &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)
{
return Tag(QLatin1String(qualified_name));
}
inline Tag tag(const char *qualified_name, const Parameters &parameters)
{
return Tag(QLatin1String(qualified_name), parameters);
}
template<class T>
inline Object<T> tag(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>
inline Object<T> tag(const QString &qualified_name, T &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 {
public:
explicit End() { }
explicit End()
{
}
explicit End(const Parameters &parameters)
: _parameters(parameters)
{
}
Parameters getParameters() const { return _parameters; }
private:
Parameters _parameters;
};
inline End end()
@@ -104,6 +153,10 @@ inline End end()
return End();
}
inline End end(const Parameters &parameters)
{
return End(parameters);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -57,6 +57,7 @@ public:
void end() override;
void registerTranslationUnitsForEditor(const RegisterTranslationUnitForEditorMessage &message) override;
void updateTranslationUnitsForEditor(const UpdateTranslationUnitsForEditorMessage &message) override;
void unregisterTranslationUnitsForEditor(const UnregisterTranslationUnitsForEditorMessage &message) override;
void registerProjectPartsForEditor(const RegisterProjectPartsForEditorMessage &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
}
const QString Preprocessor::configurationFileName = QLatin1String("<configuration>");
QString Preprocessor::configurationFileName() { return QStringLiteral("<configuration>"); }
Preprocessor::Preprocessor(Client *client, Environment *env)
: 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)
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)
value = false; // take the branch

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -49,17 +49,17 @@ std::wstring StackFrame::fileName() 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 << '"';
if (!function.empty()) {
// Split into module/function
const std::wstring::size_type exclPos = function.find('!');
if (exclPos == std::wstring::npos) {
str << ",func=\"" << gdbmiWStringFormat(function) << '"';
str << ",function=\"" << gdbmiWStringFormat(function) << '"';
} else {
const std::wstring module = function.substr(0, exclPos);
const std::wstring fn = function.substr(exclPos + 1, function.size() - exclPos - 1);
str << ",func=\"" << gdbmiWStringFormat(fn)
str << ",function=\"" << gdbmiWStringFormat(fn)
<< "\",from=\"" << gdbmiWStringFormat(module) << '"';
}
}

View File

@@ -263,7 +263,6 @@ struct TransformImpl {
static C call(const SC &container, F function)
{
C result;
result.reserve(container.size());
std::transform(container.begin(), container.end(),
inserter(result),
function);
@@ -337,6 +336,29 @@ auto transform(const SC &container, R (S::*p)() const)
>::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
/////////////////

View File

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

View File

@@ -84,6 +84,7 @@ class QTCREATOR_UTILS_EXPORT FancyLineEdit : public CompletingLineEdit
// Validation.
Q_PROPERTY(QString initialText READ initialText WRITE setInitialText DESIGNABLE true)
Q_PROPERTY(QColor errorColor READ errorColor WRITE setErrorColor DESIGNABLE true)
Q_PROPERTY(QColor okColor READ okColor WRITE setOkColor DESIGNABLE true)
public:
enum Side {Left = 0, Right = 1};
@@ -141,18 +142,17 @@ public:
void setInitialText(const QString &);
QColor errorColor() const;
void setErrorColor(const QColor &);
void setErrorColor(const QColor &c);
// Trigger an update (after changing settings)
void triggerChanged();
static QColor textColor(const QWidget *w);
static void setTextColor(QWidget *w, const QColor &c);
QColor okColor() const;
void setOkColor(const QColor &c);
void setValidationFunction(const ValidationFunction &fn);
static ValidationFunction defaultValidationFunction();
void validate();
void onEditingFinished();
protected slots:
protected:
// Custom behaviour can be added here.
virtual void handleChanged(const QString &) {}
@@ -166,17 +166,14 @@ signals:
void validChanged(bool validState);
void validReturnPressed();
private slots:
void iconClicked();
void onTextChanged(const QString &);
void onEditingFinished();
protected:
void resizeEvent(QResizeEvent *e);
virtual QString fixInputString(const QString &string);
private:
void iconClicked();
static bool validateWithValidator(FancyLineEdit *edit, QString *errorMessage);
// Unimplemented, to force the user to make a decision on
// 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"));
const QString JsonSchema::kProperties(QLatin1String("properties"));
const QString JsonSchema::kPatternProperties(QLatin1String("patternProperties"));
const QString JsonSchema::kAdditionalProperties(QLatin1String("additionalProperties"));
const QString JsonSchema::kItems(QLatin1String("items"));
const QString JsonSchema::kAdditionalItems(QLatin1String("additionalItems"));
const QString JsonSchema::kRequired(QLatin1String("required"));
const QString JsonSchema::kDependencies(QLatin1String("dependencies"));
const QString JsonSchema::kMinimum(QLatin1String("minimum"));
const QString JsonSchema::kMaximum(QLatin1String("maximum"));
const QString JsonSchema::kExclusiveMinimum(QLatin1String("exclusiveMinimum"));
const QString JsonSchema::kExclusiveMaximum(QLatin1String("exclusiveMaximum"));
const QString JsonSchema::kMinItems(QLatin1String("minItems"));
const QString JsonSchema::kMaxItems(QLatin1String("maxItems"));
const QString JsonSchema::kUniqueItems(QLatin1String("uniqueItems"));
const QString JsonSchema::kPattern(QLatin1String("pattern"));
const QString JsonSchema::kMinLength(QLatin1String("minLength"));
const QString JsonSchema::kMaxLength(QLatin1String("maxLength"));
const QString JsonSchema::kTitle(QLatin1String("title"));
const QString JsonSchema::kDescription(QLatin1String("description"));
const QString JsonSchema::kExtends(QLatin1String("extends"));
const QString JsonSchema::kRef(QLatin1String("$ref"));
QString JsonSchema::kType() { return QStringLiteral("type"); }
QString JsonSchema::kProperties() { return QStringLiteral("properties"); }
QString JsonSchema::kPatternProperties() { return QStringLiteral("patternProperties"); }
QString JsonSchema::kAdditionalProperties() { return QStringLiteral("additionalProperties"); }
QString JsonSchema::kItems() { return QStringLiteral("items"); }
QString JsonSchema::kAdditionalItems() { return QStringLiteral("additionalItems"); }
QString JsonSchema::kRequired() { return QStringLiteral("required"); }
QString JsonSchema::kDependencies() { return QStringLiteral("dependencies"); }
QString JsonSchema::kMinimum() { return QStringLiteral("minimum"); }
QString JsonSchema::kMaximum() { return QStringLiteral("maximum"); }
QString JsonSchema::kExclusiveMinimum() { return QStringLiteral("exclusiveMinimum"); }
QString JsonSchema::kExclusiveMaximum() { return QStringLiteral("exclusiveMaximum"); }
QString JsonSchema::kMinItems() { return QStringLiteral("minItems"); }
QString JsonSchema::kMaxItems() { return QStringLiteral("maxItems"); }
QString JsonSchema::kUniqueItems() { return QStringLiteral("uniqueItems"); }
QString JsonSchema::kPattern() { return QStringLiteral("pattern"); }
QString JsonSchema::kMinLength() { return QStringLiteral("minLength"); }
QString JsonSchema::kMaxLength() { return QStringLiteral("maxLength"); }
QString JsonSchema::kTitle() { return QStringLiteral("title"); }
QString JsonSchema::kDescription() { return QStringLiteral("description"); }
QString JsonSchema::kExtends() { return QStringLiteral("extends"); }
QString JsonSchema::kRef() { return QStringLiteral("$ref"); }
JsonSchema::JsonSchema(JsonObjectValue *rootObject, const JsonSchemaManager *manager)
: m_manager(manager)
@@ -169,11 +169,11 @@ JsonSchema::JsonSchema(JsonObjectValue *rootObject, const JsonSchemaManager *man
bool JsonSchema::isTypeConstrained() const
{
// Simple types
if (JsonStringValue *sv = getStringValue(kType, currentValue()))
if (JsonStringValue *sv = getStringValue(kType(), currentValue()))
return isCheckableType(sv->value());
// Union types
if (JsonArrayValue *av = getArrayValue(kType, currentValue())) {
if (JsonArrayValue *av = getArrayValue(kType(), currentValue())) {
QTC_ASSERT(currentIndex() != -1, return false);
QTC_ASSERT(av->elements().at(currentIndex())->kind() == JsonValue::String, return false);
JsonStringValue *sv = av->elements().at(currentIndex())->toString();
@@ -186,11 +186,11 @@ bool JsonSchema::isTypeConstrained() const
bool JsonSchema::acceptsType(const QString &type) const
{
// Simple types
if (JsonStringValue *sv = getStringValue(kType, currentValue()))
if (JsonStringValue *sv = getStringValue(kType(), currentValue()))
return typeMatches(sv->value(), type);
// Union types
if (JsonArrayValue *av = getArrayValue(kType, currentValue())) {
if (JsonArrayValue *av = getArrayValue(kType(), currentValue())) {
QTC_ASSERT(currentIndex() != -1, return false);
QTC_ASSERT(av->elements().at(currentIndex())->kind() == JsonValue::String, return false);
JsonStringValue *sv = av->elements().at(currentIndex())->toString();
@@ -204,13 +204,13 @@ QStringList JsonSchema::validTypes(JsonObjectValue *v)
{
QStringList all;
if (JsonStringValue *sv = getStringValue(kType, v))
if (JsonStringValue *sv = getStringValue(kType(), v))
all.append(sv->value());
if (JsonObjectValue *ov = getObjectValue(kType, v))
if (JsonObjectValue *ov = getObjectValue(kType(), v))
return validTypes(ov);
if (JsonArrayValue *av = getArrayValue(kType, v)) {
if (JsonArrayValue *av = getArrayValue(kType(), v)) {
foreach (JsonValue *v, av->elements()) {
if (JsonStringValue *sv = v->toString())
all.append(sv->value());
@@ -252,14 +252,14 @@ QStringList JsonSchema::validTypes() const
bool JsonSchema::hasTypeSchema() const
{
return getObjectValue(kType, currentValue());
return getObjectValue(kType(), currentValue());
}
void JsonSchema::enterNestedTypeSchema()
{
QTC_ASSERT(hasTypeSchema(), return);
enter(getObjectValue(kType, currentValue()));
enter(getObjectValue(kType(), currentValue()));
}
QStringList JsonSchema::properties(JsonObjectValue *v) const
@@ -268,7 +268,7 @@ QStringList JsonSchema::properties(JsonObjectValue *v) const
QStringList all;
if (JsonObjectValue *ov = getObjectValue(kProperties, v)) {
if (JsonObjectValue *ov = getObjectValue(kProperties(), v)) {
const MemberConstIterator cend = ov->members().constEnd();
for (MemberConstIterator it = ov->members().constBegin(); it != cend; ++it)
if (hasPropertySchema(it.key()))
@@ -291,7 +291,7 @@ QStringList JsonSchema::properties() const
JsonObjectValue *JsonSchema::propertySchema(const QString &property,
JsonObjectValue *v) const
{
if (JsonObjectValue *ov = getObjectValue(kProperties, v)) {
if (JsonObjectValue *ov = getObjectValue(kProperties(), v)) {
JsonValue *member = ov->member(property);
if (member && member->kind() == JsonValue::Object)
return member->toObject();
@@ -329,14 +329,14 @@ bool JsonSchema::hasItemSchema() const
{
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false);
return getObjectValue(kItems, currentValue());
return getObjectValue(kItems(), currentValue());
}
void JsonSchema::enterNestedItemSchema()
{
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);
return getArrayValue(kItems, currentValue());
return getArrayValue(kItems(), currentValue());
}
int JsonSchema::itemArraySchemaSize() const
{
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(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);
}
@@ -391,12 +391,12 @@ bool JsonSchema::maybeEnterNestedArraySchema(int index)
*/
bool JsonSchema::hasUnionSchema() const
{
return getArrayValue(kType, currentValue());
return getArrayValue(kType(), currentValue());
}
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(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);
}
@@ -430,7 +430,7 @@ void JsonSchema::leaveNestedSchema()
bool JsonSchema::required() const
{
if (JsonBooleanValue *bv = getBooleanValue(kRequired, currentValue()))
if (JsonBooleanValue *bv = getBooleanValue(kRequired(), currentValue()))
return bv->value();
return false;
@@ -440,21 +440,21 @@ bool JsonSchema::hasMinimum() const
{
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false);
return getDoubleValue(kMinimum, currentValue());
return getDoubleValue(kMinimum(), currentValue());
}
double JsonSchema::minimum() const
{
QTC_ASSERT(hasMinimum(), return 0);
return getDoubleValue(kMinimum, currentValue())->value();
return getDoubleValue(kMinimum(), currentValue())->value();
}
bool JsonSchema::hasExclusiveMinimum()
{
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 false;
@@ -464,21 +464,21 @@ bool JsonSchema::hasMaximum() const
{
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Int)), return false);
return getDoubleValue(kMaximum, currentValue());
return getDoubleValue(kMaximum(), currentValue());
}
double JsonSchema::maximum() const
{
QTC_ASSERT(hasMaximum(), return 0);
return getDoubleValue(kMaximum, currentValue())->value();
return getDoubleValue(kMaximum(), currentValue())->value();
}
bool JsonSchema::hasExclusiveMaximum()
{
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 false;
@@ -488,7 +488,7 @@ QString JsonSchema::pattern() const
{
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 QString();
@@ -498,7 +498,7 @@ int JsonSchema::minimumLength() const
{
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 -1;
@@ -508,7 +508,7 @@ int JsonSchema::maximumLength() const
{
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 -1;
@@ -518,7 +518,7 @@ bool JsonSchema::hasAdditionalItems() const
{
QTC_ASSERT(acceptsType(JsonValue::kindToString(JsonValue::Array)), return false);
return currentValue()->member(kAdditionalItems);
return currentValue()->member(kAdditionalItems());
}
bool JsonSchema::maybeSchemaName(const QString &s)
@@ -600,7 +600,7 @@ void JsonSchema::leave()
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());
if (referenced)
return referenced->rootValue();
@@ -611,7 +611,7 @@ JsonObjectValue *JsonSchema::resolveReference(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) {
JsonSchema *schema = m_manager->schemaByName(v->toString()->value());
if (schema)

View File

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

View File

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

View File

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

View File

@@ -336,6 +336,16 @@ void PathChooser::setFileName(const FileName &fn)
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
{
return d->m_lineEdit->isReadOnly();
@@ -453,7 +463,7 @@ QString PathChooser::errorMessage() const
void PathChooser::triggerChanged()
{
d->m_lineEdit->triggerChanged();
d->m_lineEdit->validate();
}
void PathChooser::setAboutToShowContextMenuHandler(PathChooser::AboutToShowContextMenuHandler handler)
@@ -461,6 +471,16 @@ void PathChooser::setAboutToShowContextMenuHandler(PathChooser::AboutToShowConte
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
{
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)
return;
d->m_acceptingKind = expected;
d->m_lineEdit->triggerChanged();
d->m_lineEdit->validate();
}
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:
Q_PROPERTY(Utils::FileName fileName READ fileName WRITE setFileName 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:
static QString browseButtonLabel();
@@ -145,6 +147,9 @@ public:
using AboutToShowContextMenuHandler = std::function<void (Utils::PathChooser *, QMenu *)>;
static void setAboutToShowContextMenuHandler(AboutToShowContextMenuHandler handler);
QColor errorColor() const;
QColor okColor() const;
private:
bool validatePath(FancyLineEdit *edit, QString *errorMessage) const;
// Returns overridden title or the one from <title>
@@ -165,6 +170,9 @@ public slots:
void setPath(const QString &);
void setFileName(const Utils::FileName &);
void setErrorColor(const QColor &errorColor);
void setOkColor(const QColor &okColor);
private:
PathChooserPrivate *d;
static AboutToShowContextMenuHandler s_aboutToShowContextMenuHandler;

View File

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

View File

@@ -28,20 +28,30 @@
**
****************************************************************************/
#ifndef CUSTOMWIZARDPREPROCESSOR_H
#define CUSTOMWIZARDPREPROCESSOR_H
#ifndef TEMPLATEENGINE_H
#define TEMPLATEENGINE_H
#include "utils_global.h"
#include "macroexpander.h"
#include <QString>
QT_FORWARD_DECLARE_CLASS(QJSEngine)
QT_FORWARD_DECLARE_CLASS(QJSEngine);
namespace ProjectExplorer {
namespace Internal {
namespace Utils {
bool customWizardPreprocess(const QString &in, QString *out, QString *errorMessage);
/* Helper to evaluate an expression. */
bool evaluateBooleanJavaScriptExpression(QJSEngine &engine, const QString &expression, bool *result, QString *errorMessage);
} // namespace Internal
} // namespace ProjectExplorer
class QTCREATOR_UTILS_EXPORT TemplateEngine {
public:
static bool preprocessText(const QString &input, QString *output, QString *errorMessage);
#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
}
QT += network
QT += gui network qml
CONFIG += exceptions # used by portlist.cpp, textfileformat.cpp, and ssh/*
@@ -16,6 +16,7 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/shellcommandpage.cpp \
$$PWD/settingsselector.cpp \
$$PWD/stringutils.cpp \
$$PWD/templateengine.cpp \
$$PWD/textfieldcheckbox.cpp \
$$PWD/textfieldcombobox.cpp \
$$PWD/filesearch.cpp \
@@ -108,6 +109,7 @@ HEADERS += \
$$PWD/shellcommand.h \
$$PWD/shellcommandpage.h \
$$PWD/stringutils.h \
$$PWD/templateengine.h \
$$PWD/textfieldcheckbox.h \
$$PWD/textfieldcombobox.h \
$$PWD/filesearch.h \

View File

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

View File

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

View File

@@ -70,15 +70,15 @@ bool AnalyzerAction::isRunnable(QString *reason) const
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)
return true;
if (buildType == BuildConfiguration::Debug && toolMode == DebugMode)
if (buildType == BuildConfiguration::Debug && (toolMode & DebugMode))
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 false;
}
@@ -114,30 +114,53 @@ void AnalyzerAction::startTool()
// 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 (!buildTypeAccepted(m_toolMode, buildType)) {
const QString currentMode = buildType == BuildConfiguration::Debug
? AnalyzerManager::tr("Debug")
: AnalyzerManager::tr("Release");
QString toolModeString;
switch (m_toolMode) {
case DebugMode:
toolModeString = AnalyzerManager::tr("Debug");
QString currentMode;
switch (buildType) {
case BuildConfiguration::Debug:
currentMode = AnalyzerManager::tr("Debug");
break;
case ReleaseMode:
toolModeString = AnalyzerManager::tr("Release");
case BuildConfiguration::Profile:
currentMode = AnalyzerManager::tr("Profile");
break;
case BuildConfiguration::Release:
currentMode = AnalyzerManager::tr("Release");
break;
default:
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 message = AnalyzerManager::tr("<html><head/><body><p>You are trying "
"to run the tool \"%1\" on an application in %2 mode. "
"The tool is designed to be used in %3 mode.</p><p>"
"Debug and Release mode run-time characteristics differ "
"significantly, analytical findings for one mode may or "
"may not be relevant for the other.</p><p>"
"The tool is designed to be used %3.</p><p>"
"Run-time characteristics differ significantly between "
"optimized and non-optimized binaries. Analytical "
"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>")
.arg(toolName).arg(currentMode).arg(toolModeString);
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 memcheck tool, for example, requires debug symbols, hence DebugMode
* is preferred. On the other hand, callgrind should look at optimized code,
* hence ReleaseMode.
* Debugging tools which try to show stack traces as close as possible to what the source code
* looks like will prefer SymbolsMode. Profiling tools which need optimized code for realistic
* performance, but still want to show analytical output that depends on debug symbols, will prefer
* ProfileMode.
*/
enum ToolMode {
DebugMode,
ReleaseMode,
AnyMode
DebugMode = 0x1,
ProfileMode = 0x2,
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.
@@ -84,7 +89,7 @@ public:
Core::Id toolId() const { return m_toolId; }
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; }
void setRunMode(Core::Id mode) { m_runMode = mode; }
@@ -118,7 +123,7 @@ protected:
Core::Id m_menuGroup;
Core::Id m_actionId;
Core::Id m_toolId;
ToolMode m_toolMode;
QFlags<ToolMode> m_toolMode;
Core::Id m_runMode;
WidgetCreator m_widgetCreator;
RunControlCreator m_runControlCreator;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -53,6 +53,7 @@ class DiagnosticsChangedMessage;
namespace TextEditor {
class TextEditorWidget;
class TextDocument;
}
namespace ClangCodeModel {
@@ -96,6 +97,7 @@ public:
virtual void end() = 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 registerProjectPartsForEditor(const ClangBackEnd::RegisterProjectPartsForEditorMessage &message) = 0;
virtual void unregisterProjectPartsForEditor(const ClangBackEnd::UnregisterProjectPartsForEditorMessage &message) = 0;
@@ -118,6 +120,7 @@ public:
IpcCommunicator();
void registerTranslationUnitsForEditor(const FileContainers &fileContainers);
void updateTranslationUnitsForEditor(const FileContainers &fileContainers);
void unregisterTranslationUnitsForEditor(const FileContainers &fileContainers);
void registerProjectPartsForEditor(const ProjectPartContainers &projectPartContainers);
void unregisterProjectPartsForEditor(const QStringList &projectPartIds);
@@ -130,6 +133,8 @@ public:
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 updateTranslationUnit(Core::IDocument *document);
void updateUnsavedFile(Core::IDocument *document);
@@ -138,6 +143,7 @@ public:
void updateTranslationUnit(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(Core::IDocument *document);
void updateChangeContentStartPosition(const QString &filePath, int position);
public: // for tests

View File

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

View File

@@ -104,7 +104,7 @@ QtcPlugin {
condition: project.testsEnabled
prefix: "test/"
files: [
"clang_tests_database.qrc",
"data/clangtestdata.qrc",
"clangcodecompletion_test.cpp",
"clangcodecompletion_test.h",
]
@@ -112,20 +112,10 @@ QtcPlugin {
Group {
name: "Test resources"
prefix: "test/"
prefix: "test/data/"
fileTags: "none"
files: [
"mysource.cpp",
"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: [ "*" ]
excludeFiles: "clangtestdata.qrc"
}
files: [

View File

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

View File

@@ -83,7 +83,7 @@ private:
};
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 handleAvailableCompletions(const CodeCompletions &completions);

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