How to translate default qsTr fields - e.g. MessageDialog Yes / No buttons - qt

I have a small app that uses a Qt Quick MessageDialog. I created translations files with command
lupdate-qt5 ../myapp.pro .
In myapp.pro I indicated:
lupdate_only {
SOURCES += $$PWD/ui/*.qml
}
and
TRANSLATIONS += \
translations/i18n_nl.ts translations/i18n_fr.ts translations/i18n_en.ts
All translations are generated correctly. But I have no idea how to generate translations for the standard buttons that MessageDialog provides. In the following example the translations for "Warning" and "Please select Yes or No" are generated. But I can't get them generated for "Yes" and "No" (which is the text value of the StandardButtons property)
MessageDialog {
title: qsTr("Warning")
text: qsTr("Please select Yes or No")
icon: StandardIcon.Warning
standardButtons: StandardButton.Yes | StandardButton.No
//.....
}
I have checked the source code and it indicates that they should be translated:
Button {
id: yesButton
text: qsTr("Yes")
onClicked: root.click(StandardButton.Yes)
visible: root.standardButtons & StandardButton.Yes
}
I've also tried manually adding an entry Yes and No but that doesn't seem to help.
I've found an issue on stackoverflow that talks about adding the qml file to the .pro file to make it work, and that is something I already do. I though about adding the built-in MessageDialog, but I have no idea how to do this.
As a final note: I know that in Qt 5.3 the qsTr's weren't in MessageDialog. But starting from Qt 5.4 they are. I am currently on Qt 5.5
Any help is greatly appreciated.
EDIT
After posting this I kept looking and found an interesting post of someone who has had the same issue. Unfortunately, no answer there.
EDIT 2
Thank you tynn for the response. I have tried both suggestions but no succes. I did try something else as well. I added a qDebug in my code to see if it would translate. I was hoping the same translation would then be used for the MessageDialog, but unfortunatly that doesn't seem to be the case.
qDebug() << "Translate yes :" << tr("Yes"); //translates correctly, dialog doesn't
I have also tried to build a dialog from scratch that does the same as the built-in messagedialog, but at the moment my knowledge of qml is too limited to get this working.

Well, it may be a bit tricky.
First of all, localized strings for Qt widgets may be in Qt's .qm files. Remember that in general you will need all Qt's .qm files for locales you translate into. That's because Qt may, for example, use native MessageDialogs on platforms where they are available, and related code in this case will be located in qtbase, so you will need not only qtquickcontrols_XX.qm files, but also qtbase_XX.qm files for selected locales. And so on.
However, there may be cases when the above does not help. Required strings may simply be missing in the Qt's localization files for your locale (it's a quite common), so you will need to make .ts and .qm files for these strings by yourself. In this case you will need to study Qt sources in order to understand internals of those widgets you are interested in.
Please note that the following example depends on implementation details which may change in future Qt versions.
For example, Qt implementation of QML MessageDialog for Android and iOS uses QPlatformTheme that may be further subclassed to work with different platforms. In QPlatformTheme texts for button labels are returned by defaultStandardButtonText() method which looks like this:
QString QPlatformTheme::defaultStandardButtonText(int button)
{
switch (button) {
case QPlatformDialogHelper::Ok:
return QCoreApplication::translate("QPlatformTheme", "OK");
case QPlatformDialogHelper::Save:
return QCoreApplication::translate("QPlatformTheme", "Save");
case QPlatformDialogHelper::SaveAll:
return QCoreApplication::translate("QPlatformTheme", "Save All");
case QPlatformDialogHelper::Open:
return QCoreApplication::translate("QPlatformTheme", "Open");
case QPlatformDialogHelper::Yes:
return QCoreApplication::translate("QPlatformTheme", "&Yes");
case QPlatformDialogHelper::YesToAll:
return QCoreApplication::translate("QPlatformTheme", "Yes to &All");
case QPlatformDialogHelper::No:
return QCoreApplication::translate("QPlatformTheme", "&No");
case QPlatformDialogHelper::NoToAll:
return QCoreApplication::translate("QPlatformTheme", "N&o to All");
case QPlatformDialogHelper::Abort:
return QCoreApplication::translate("QPlatformTheme", "Abort");
case QPlatformDialogHelper::Retry:
return QCoreApplication::translate("QPlatformTheme", "Retry");
case QPlatformDialogHelper::Ignore:
return QCoreApplication::translate("QPlatformTheme", "Ignore");
case QPlatformDialogHelper::Close:
return QCoreApplication::translate("QPlatformTheme", "Close");
case QPlatformDialogHelper::Cancel:
return QCoreApplication::translate("QPlatformTheme", "Cancel");
case QPlatformDialogHelper::Discard:
return QCoreApplication::translate("QPlatformTheme", "Discard");
case QPlatformDialogHelper::Help:
return QCoreApplication::translate("QPlatformTheme", "Help");
case QPlatformDialogHelper::Apply:
return QCoreApplication::translate("QPlatformTheme", "Apply");
case QPlatformDialogHelper::Reset:
return QCoreApplication::translate("QPlatformTheme", "Reset");
case QPlatformDialogHelper::RestoreDefaults:
return QCoreApplication::translate("QPlatformTheme", "Restore Defaults");
default:
break;
}
return QString();
}
So, in order to localize Yes/No buttons, you will need to add in your .ts file the following:
<context>
<name>QPlatformTheme</name>
<message>
<source>&Yes</source>
<translation>[...]</translation>
</message>
<message>
<source>&No</source>
<translation>[...]</translation>
</message>
</context>
Android have its own subclassed platform theme (QAndroidPlatformTheme) with overriden defaultStandardButtonText(), so for Android you will need to add the following:
<context>
<name>QAndroidPlatformTheme</name>
<message>
<source>Yes</source>
<translation>[...]</translation>
</message>
<message>
<source>No</source>
<translation>[...]</translation>
</message>
</context>
iOS does not override this method in its own QPlatformTheme subclass, so no additional action is needed for it.
You can take a look on one of my projects which use the technique described above for QML MessageBox localization on Android and iOS.

The translations you need should be found inside a qtquickcontrols_*.qm file. Deploying Translations states concerning this
Usually, there are .qm files for the application, and, if a version of Qt is used that is not installed on the system, Qt's .qm files need to be deployed as well.
However your application might just fail to find a suitable translation file. If you only need the translations for Yes and No, you could as well add these to your translation files with a context of DefaultMessageDialog
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1">
<context>
<name>DefaultMessageDialog</name>
<message>
<source>Yes</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>No</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>
Adding the built-in MessageDialog would work as well. Or if you'd like to, you could just use a dummy file DefaultMessageDialog.qml
Rectangle {
Button {
id: yesButton
text: qsTr("Yes")
}
Button {
id: noButton
text: qsTr("No")
}
}
and add this one instead.

On Desktop platforms, such as Windows, macOS and Linux, most Dialog components from QtQuick.Dialogs uses C++ widget components. Their source translations are covered in qtbase_{lang}.ts files and their compiled translations are covered in qtbase_{lang}.qmfiles.
In Qt5.13.1:
refer to C:\Qt\Qt5.13.1\5.13.1\Src\qttranslations\translations for source translations
refer to C:\Qt\Qt5.13.1\5.13.1\mingw83_64\translations for the compiled translations
If you find the sizes of qtbase to be too large for your liking, you can deploy a minified version of the translation files. The following Windows Batch file creates French, German and Japanese subsets of the qtbase files:
setlocal
set QTDIR=C:\Qt\Qt5.13.1\5.13.1\msvc2017_64\
set QTSRC=C:\Qt\Qt5.13.1\5.13.1\Src
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qmessagebox.cpp > %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qfiledialog.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qcolordialog.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qfontdialog.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qinputdialog.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qprogressdialog.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\widgets\dialogs\qwizard.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\gui\kernel\qplatformtheme.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\plugins\platforms\android\qandroidplatformtheme.cpp >> %TEMP%\qtbase_min.lst
ECHO %QTSRC%\qtbase\src\platformsupport\themes\genericunix\qgenericunixthemes.cpp >> %TEMP%\qtbase_min.lst
for /d %%F in (fr de ja en) do copy %QTSRC%\qttranslations\translations\qtbase_%%F.ts qtbase_min_%%F.ts
%QTDIR%\bin\lupdate #%TEMP%/qtbase_min.lst -pluralonly -locations none -ts qtbase_min_en.ts
for /d %%F in (fr de ja en) do if "%%F" neq "en" %QTDIR%\bin\lupdate.exe #%TEMP%/qtbase_min.lst -no-obsolete -locations none -ts qtbase_min_%%F.ts
for /d %%F in (fr de ja en) do %QTDIR%\bin\lrelease qtbase_min_%%F.ts
On mobile platforms, such as iOS and Android, Dialog the MessageDialog component the translatable text are still covered in the qtbase_{lang}.ts files. For the other components, such as ColorDialog, FontDialog, they are implemented in QML as QtQuick components. The translations will be found in the qtquickcontrols_{lang}.ts and qtquickcontrols_{lang}.qm files.
The following demonstrates how to create minified versions of the qtquickcontrols_{lang}.ts and qtquickcontrols_{lang}.qm files for French, German and Japanese:
setlocal
set QTDIR=C:\Qt\Qt5.13.1\5.13.1\msvc2017_64\
set QTSRC=C:\Qt\Qt5.13.1\5.13.1\Src
ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultMessageDialog.qml > %TEMP%\qtquickcontrols_min.lst
ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultColorDialog.qml >> %TEMP%\qtquickcontrols_min.lst
ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultFileDialog.qml >> %TEMP%\qtquickcontrols_min.lst
ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultFontDialog.qml >> %TEMP%\qtquickcontrols_min.lst
ECHO %QTSRC%\qtquickcontrols\src\dialogs\DefaultDialogWrapper.qml >> %TEMP%\qtquickcontrols_min.lst
for /d %%F in (fr de ja en) do copy %QTSRC%\qttranslations\translations\qtquickcontrols_%%F.ts qtquickcontrols_min_%%F.ts
%QTDIR%\bin\lupdate #%TEMP%/qtquickcontrols_min.lst -pluralonly -locations none -ts qtquickcontrols_min_en.ts
for /d %%F in (fr de ja en) do if "%%F" neq "en" %QTDIR%\bin\lupdate.exe #%TEMP%/qtquickcontrols_min.lst -no-obsolete -locations none -ts qtquickcontrols_min_%%F.ts
for /d %%F in (fr de ja en) do %QTDIR%\bin\lrelease qtquickcontrols_min_%%F.ts
Presently, at Qt5.13.1, there are 22 languages (including English). If your desired language is not covered in this list (e.g. Indonesian, Vietnamese), then, you can still use the above scripts to create placeholder minified version of qtbase/qtquickcontrols but you will have to populate the qtbase_min_{lang}.ts files yourself.

Related

CMake 3.17 deletes Qt translations when updating the TS files

Update: Simplified problem
With CMake 3.16.8 or less, the following workflow was working, but 3.17+ deletes the Qt's TS files.
The idea is taken from Professional CMake, 7th Edition by Craig Scott
Requirements
cmake 3.17+, Qt 5.9+, ninja
Concept
To update the translation files for Qt, UPDATE_TRANSLATIONS can be enabled. When finished, disable it.
CMake 3.17+ deletes the updated TS files.
Adjust pathes in the script update_translation.sh to automate the workflow.
Steps to reproduce
git clone https://github.com/Macintron/QtTranslationDemo.git # or create files from below in QtTranslationDemo.
mkdir build # NOT in QtTranslationDemo
cd build
cmake -G Ninja -DCMAKE_PREFIX_PATH=[pathToQtDir/5.15.1/clang_64] ../QtTranslationDemo
ninja
./demo
Output should be:
Demo
de.qm: 85 bytes
Language: 'Deutsch'
greeting: ''
en.qm: 85 bytes
Language: 'English'
greeting: ''
now the problem starts:
cmake -DUPDATE_TRANSLATIONS=ON ../QtTranslationDemo
ninja demoTranslations
cmake -DUPDATE_TRANSLATIONS=OFF ../QtTranslationDemo
# new strings ("greeting") should haven been added to the ts files, but TS files are deleted instead!
Why are the TS files get deleted? Is this a bug in CMake 3.17+ or a bug in my workflow?
build info
The build directory must NOT be inside the sources.
Source files
CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(QtTranslationDemo LANGUAGES CXX)
find_package(Qt5
COMPONENTS
LinguistTools Core
REQUIRED
)
option(UPDATE_TRANSLATIONS "Enable rescanning sources to update .ts files" OFF)
set(_tsFiles en.ts de.ts)
if(UPDATE_TRANSLATIONS)
message("** parse sources for new translations")
qt5_create_translation(_qmFiles
main.cpp
${_tsFiles}
)
else()
message("** update qm files")
qt5_add_translation(_qmFiles
${_tsFiles}
)
endif()
add_custom_target(demoTranslations DEPENDS ${_qmFiles})
add_executable(demo
main.cpp
${_qmFiles}
)
target_link_libraries(demo
PUBLIC
Qt5::Core
)
main.cpp
#include <QTranslator>
#include <QDir>
#include <QStringList>
static const char* language = QT_TRANSLATE_NOOP("#default", "Language");
static const char* greeting = QT_TRANSLATE_NOOP("#default", "greeting"); // not in ts files now!
int main(int argc, char *argv[])
{
qDebug("Demo");
QStringList qms = QDir("./").entryList({"*.qm"});
for (const auto& qm: qms) {
qDebug("%s: %lld bytes", qPrintable(qm), QFileInfo("./" + qm).size());
QTranslator appTranslator;
if (appTranslator.load(qm, "./")) {
qDebug(" Language: '%s'", qPrintable(appTranslator.translate("#default", language)));
qDebug(" greeting: '%s'", qPrintable(appTranslator.translate("#default", greeting)));
} else {
qWarning("Failed to load %s", qPrintable(qm));
}
}
return 0;
}
en.ts
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en" sourcelanguage="en">
<context>
<name>#default</name>
<message>
<source>Language</source>
<translation>English</translation>
</message>
</context>
</TS>
de.ts
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de" sourcelanguage="en">
<context>
<name>#default</name>
<message>
<source>Language</source>
<translation>Deutsch</translation>
</message>
</context>
</TS>
update_translation.sh
#!/bin/sh
set -e
thisdir=$(dirname $0)
qt_root=/usr/local/Trolltech/Qt5.15/5.15.1/clang_64
#cmaketool=/usr/local/Cellar/cmake/3.16.8/bin/cmake
cmaketool=cmake
# easier setup
rm -Rf en.qm de.qm CMakeFiles CMakeCache.txt cmake_install.cmake build.ninja .ninja_* > /dev/null 2>&1
git checkout $thisdir/de.ts $thisdir/en.ts # restore files
$cmaketool --version
$cmaketool -G Ninja -DCMAKE_PREFIX_PATH=$qt_root ../QtTranslationDemo
ninja
./demo
rm -f demo
echo "Starting CMake with DUPDATE_TRANSLATIONS..."
$cmaketool -DUPDATE_TRANSLATIONS=ON $thisdir
echo
echo "Updating translation files..."
ninja demoTranslations
echo
echo "Restore CMake configuration..."
$cmaketool -DUPDATE_TRANSLATIONS=OFF $thisdir
ninja
./demo
exit 0
This was a generic CMake problem, caused by the cleandead feature. It should be fixed in CMake 3.19.2.
Thank you all for your contributions to solve the problem.

Default Representation/Drawing method in VMD

In VMD I want to load every new file with the drawing method CPK. This doesn't seem not to be an option in the .vmdrc file for some technical reasons.
How can I do this from the VMD command line (so that I can make a script)?
Or is there some other solution/workaround/hack to make this work?
There are several ways to achieve what you want:
(1) put the following line in the correct location of your .vmdrc
mol default style CPK
(2) use the VMD Preferences Panel (last item in the Extensions menu of the main window) to generate a .vmdrc file that meets your expectations(s). The setting you're looking for is in the Representations tab.
(3) for more advanced settings (i.e. default settings applied to molecules already loaded when vmd read the startup .vmdrc file), you can use the following (works for me on VMD 1.9.2):
proc reset_viz {molid} {
# operate only on existing molecules
if {[lsearch [molinfo list] $molid] >= 0} {
# delete all representations
set numrep [molinfo $molid get numreps]
for {set i 0} {$i < $numrep} {incr i} {
mol delrep $i $molid
}
# add new representations
mol representation CPK
# add other representation stuff you want here
mol addrep $molid
}
}
proc reset_viz_proxy {args} {
foreach {fname molid rw} $args {}
eval "after idle {reset_viz $molid}"
}
## put a trace on vmd_initialize_structure
trace variable vmd_initialize_structure w reset_viz_proxy
after idle {
if { 1 } {
foreach molid [molinfo list] {
reset_viz $molid
}
}
}
This piece of code is adapted from this Axel Kohlmeyer website.
HTH,
I found a convenient solution.
In .bashrc add:
vmda () {
echo -e "
mol default style CPK
user add key Control-w quit
" > /tmp/vmdstartup
echo "mol new $1" > /tmp/vmdcommand
vmd -e /tmp/vmdcommand -startup /tmp/vmdstartup
}
Look at a structure with
vmda file.pdb
and close the window (quit the application) with Ctrl+w, like other windows.

redefine \nomencl_command in LyX

I am trying to redefine the \nomencl_command in LyX, in order to be able to use the glossaries package in stead of the obsolete nomencl.
LyX allows you to specify the Nomenclature command, which by default is set to:
makeindex -s nomencl.ist
For glossaries the command is thus changed to:
makeglossaries
However, the LyX implementation of nomencl uses the more recent .nlo as an input file, and the .nls as an output file. Whereas glossaries uses the 'older' .glo and .gls Unfortunately, the extensions cannot be specified.
I found that the preferences file only says:
\nomencl_command "makeglossaries"
but the log output says:
makeglossaries "[filename].nlo" -o [filename].nls
So my question is where is \nomencl_command defined further?
The relevant code is in src/LaTeX.cpp.
Note below that some diagnostic information is written to the latex debug flag. You can see this info on the terminal if you run LyX with lyx -dbg latex.
The following are excerpts from the file src/LaTeX.cpp from the soon-to-be-released (a matter of days) LyX 2.1.
FileName const nlofile(changeExtension(file.absFileName(), ".nlo"));
// If all nomencl entries are removed, nomencl writes an empty nlo file.
// DepTable::hasChanged() returns false in this case, since it does not
// distinguish empty files from non-existing files. This is why we need
// the extra checks here (to trigger a rerun). Cf. discussions in #8905.
// FIXME: Sort out the real problem in DepTable.
if (head.haschanged(nlofile) || (nlofile.exists() && nlofile.isFileEmpty()))
rerun |= runMakeIndexNomencl(file, ".nlo", ".nls");
FileName const glofile(changeExtension(file.absFileName(), ".glo"));
if (head.haschanged(glofile))
rerun |= runMakeIndexNomencl(file, ".glo", ".gls");
and
bool LaTeX::runMakeIndexNomencl(FileName const & file,
string const & nlo, string const & nls)
{
LYXERR(Debug::LATEX, "Running MakeIndex for nomencl.");
message(_("Running MakeIndex for nomencl."));
string tmp = lyxrc.nomencl_command + ' ';
// onlyFileName() is needed for cygwin
tmp += quoteName(onlyFileName(changeExtension(file.absFileName(), nlo)));
tmp += " -o "
+ onlyFileName(changeExtension(file.toFilesystemEncoding(), nls));
Systemcall one;
one.startscript(Systemcall::Wait, tmp, path);
return true;
}
and
// nomencl file
FileName const nls(changeExtension(file.absFileName(), ".nls"));
nls.removeFile();
// nomencl file (old version of the package)
FileName const gls(changeExtension(file.absFileName(), ".gls"));
gls.removeFile();

ZendFramework 2 - PHPUnit - command line works, NetBeans states "No tests executed"

I seem to have a slight problem with executing PHPUnit tests for own modules in the Zend Framework 2.
OS: Mac OS 10.8.3
Zend Framework 2.1.4
PHPUnit Version 3.7.19 (installed via pear)
PHP Version 5.3.15 (xdebug enabled, version 2.1.3)
I followed the instructions of the Zend guideline, to create the module "Album" (http://framework.zend.com/manual/2.1/en/user-guide/modules.html)
Instead of putting the unit tests into the module folders, I want to have them all in one centralized folder. This is the base structure of my application:
-config
-data
-module
-public
-tests
--Modules
---Album
----AlbumTest.php
--Bootstrap.php
--phpunit.xml
-vendor
...(license, readme, composers and init_autoloader.php)
-> The test for the Module Album resides in a folder "Modules/Album" in "tests". The folder "tests" contains also the Bootstrap.php and phpunit.xml.
Here is the content of the files:
Bootstrap.php
<?php
/*
* Set error reporting to the level to which Zend Framework code must comply.
*/
error_reporting( E_ALL | E_STRICT );
/*
* The first run required me to fix some constants
*/
defined('TESTS_ZEND_FORM_RECAPTCHA_PUBLIC_KEY') || define('TESTS_ZEND_FORM_RECAPTCHA_PUBLIC_KEY', 'public key');
defined('TESTS_ZEND_FORM_RECAPTCHA_PRIVATE_KEY') || define('TESTS_ZEND_FORM_RECAPTCHA_PRIVATE_KEY', 'private key');
defined('TESTS_ZEND_LDAP_PRINCIPAL_NAME') || define('TESTS_ZEND_LDAP_PRINCIPAL_NAME', 'someUser#example.com');
defined('TESTS_ZEND_LDAP_ALT_USERNAME') || define('TESTS_ZEND_LDAP_ALT_USERNAME', 'anotherUser');
chdir(dirname(__DIR__));
/*
* autoload the application
*/
include __DIR__ . '/../init_autoloader.php';
Zend\Mvc\Application::init(include 'config/test.config.php');
phpunit.xml
<phpunit bootstrap="./Bootstrap.php" colors="true">
<testsuites>
<testsuite name="Zend Module Tests">
<directory>./Modules</directory>
</testsuite>
</testsuites>
</phpunit>
AlbumTest.php
<?php
namespace AlbumTest\Model;
use Album\Model\Album;
use PHPUnit_Framework_TestCase;
/**
* #category Module
* #package Album
* #subpackage UnitTests
* #group Module_Album
*/
class AlbumTest extends PHPUnit_Framework_TestCase {
public function testAlbumInitialState() {
$album = new Album();
$this->assertNull($album->artist, '"artist" should initially be null');
$this->assertNull($album->id, '"id" should initially be null');
$this->assertNull($album->title, '"title" should initially be null');
}
public function testExchangeArraySetsPropertiesCorrectly() {
$album = new Album();
$data = array('artist' => 'some artist',
'id' => 123,
'title' => 'some title');
$album->exchangeArray($data);
$this->assertSame($data['artist'], $album->artist, '"artist" was not set correctly');
$this->assertSame($data['id'], $album->id, '"id" was not set correctly');
$this->assertSame($data['title'], $album->title, '"title" was not set correctly');
}
public function testExchangeArraySetsPropertiesToNullIfKeysAreNotPresent() {
$album = new Album();
$album->exchangeArray(array('artist' => 'some artist',
'id' => 123,
'title' => 'some title'));
$album->exchangeArray(array());
$this->assertNull($album->artist, '"artist" should have defaulted to null');
$this->assertNull($album->id, '"id" should have defaulted to null');
$this->assertNull($album->title, '"title" should have defaulted to null');
}
public function testGetArrayCopyReturnsAnArrayWithPropertyValues() {
$album = new Album();
$data = array('artist' => 'some artist',
'id' => 123,
'title' => 'some title');
$album->exchangeArray($data);
$copyArray = $album->getArrayCopy();
$this->assertSame($data['artist'], $copyArray['artist'], '"artist" was not set correctly');
$this->assertSame($data['id'], $copyArray['id'], '"id" was not set correctly');
$this->assertSame($data['title'], $copyArray['title'], '"title" was not set correctly');
}
public function testInputFiltersAreSetCorrectly() {
$album = new Album();
$inputFilter = $album->getInputFilter();
$this->assertSame(3, $inputFilter->count());
$this->assertTrue($inputFilter->has('artist'));
$this->assertTrue($inputFilter->has('id'));
$this->assertTrue($inputFilter->has('title'));
}
}
NetBeans knows, where to find the phpunit binaries:
(I wanted to post images here, don't have the reputation though :), I will try to explain it)
The paths to are configured in the options - php - unit testing
/usr/local/pear/bin/phpunit and
/usr/local/pear/bin/phpunit-skelgen
In the properties of the project I set the "Use XML Configuration" and pasted the path to the phpunit.xml. I also checked "Ask for Test Groups Before Running Tests" - I gave the test above the group "Module_Album" - like this I make sure, that PHPUnit finds the right test.
I right click on Project and choose "Test", it shows me the group "Module_Album", I check it and click "Ok". It runs something, tells me it located the right phpunit.xml ("Configuration read from FULL_PATH/tests/phpunit.xml"). After running, it tells me, that it didn't execute any tests.
This is the full output in NetBeans:
PHPUnit 3.7.19 by Sebastian Bergmann.
Configuration read from FULL_PATH/tests/phpunit.xml
Time: 9 seconds, Memory: 348.25Mb
[2KNo tests executed!
[2K
Generating code coverage report in Clover XML format ... done
Anyway, I can do the same successfully via shell (terminal). It doesn't matter, if I directly mount the tests directory and run phpunit, use the full path to the phpunit binary (to make sure, that I don't use different version), specifying the full path of the phpunit.xml, and so on. Here are some samples:
phpunit
phpunit -c FULL_PATH/tests/phpunit.xml
/usr/local/pear/bin/phpunit -c FULL_PATH/tests/phpunit.xml
All of these commands give me, what I expect:
PHPUnit 3.7.19 by Sebastian Bergmann.
Configuration read from FULL_PATH/tests/phpunit.xml
.....
Time: 0 seconds, Memory: 12.75Mb
OK (5 tests, 16 assertions)
I don't get, why this works in shell but not via NetBeans
NetBeans uses 350MB, while in shell it uses only 12.75MB
In case I remove the option "Ask for Test Groups Before Running Tests", it seems to try running all ZendTests. Don't know how this is possible, from the phpunit.xml it should not find them.
Any help is appreciated, thanks!
I finally figured out, what is going on. I ran previously the ZendTests with the phpunit.xml, which is inside vendor/zendframework/zendframework/tests
For some reason NetBeans saves the testfile-directory, which it finds in the first test run and doesn't release them, if the a different phpunit.xml is chosen. I had to change the path of my "new" tests directory via "Right click on project" - "Properties" - "Sources" - "Test Folder".
Now NetBeans runs the test and gives exactly the same output like CLI.

Boost-build/BJam language - checking the value of a flag

I need to edit a .jam file used by boost-build for a specific kind of projects. The official manual on BJAM language says:
One of the toolsets that cares about DEF files is msvc. The following line should be added to it. flags msvc.link DEF_FILE
;
Since the DEF_FILE variable is not used by the msvc.link action, we need to modify it to be: actions link bind DEF_FILE { $(.LD) ....
/DEF:$(DEF_FILE) .... } Note the bind DEF_FILE part. It tells bjam to
translate the internal target name in DEF_FILE to a corresponding
filename in the link
So apparently just printing DEF_FILE with ECHO wouldn't work. How can it be expanded to a string variable or something that can actually be checked?
What I need to do is to print an error message and abort the build in case the flag is not set. I tried:
if ! $(DEF_FILE)
{
errors.user-error "file not found" ;
EXIT ;
}
but this "if" is always true
I also tried putting "if ! $_DEF_FILE {...}" inside the "actions" contained but apparently it is ignored.
I am not sure I understand the global task you have. However, if you wanted to add checking for non-empty DEF_FILE -- expanding on the documentation bit you quote, you need to add the check in msvc.link function.
If you have a command line pattern (specified with 'actions') its content is what is passed to OS for execution. But, you can also have a function with the same name, that will be called before generating the actions. For example, here's what current codebase have:
rule link.dll ( targets + : sources * : properties * )
{
DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
if <embed-manifest>on in $(properties)
{
msvc.manifest.dll $(targets) : $(sources) : $(properties) ;
}
}
You can modify this code to additionally:
if ! [ on $(<) return $(DEF_FILE) ] {
ECHO "error" ;
}

Resources