Get hold of the module that imported us in QML/Qbs - qml

As a beginner in Qbs/QML I want to get information about what instance that imported our module. For example, given this project:
.
├── a
│   └── imported.qbs
└── b
└── main.qbs
with a/imported.qbs like this:
Product{
name:{
console.info("I was imported from" + XXX);
return "imported"
}
}
and b/main.qbs like this:
import "../a/imported.qbs" as Imported
Imported {}
When I run main.qbs, how could I get the instance that imported imported.qbs (main.qbs)?
Or in other words, what should I susbstitute for XXX to print main.qbs.

I don't think you can get the file name of the instantiating item, nor should it be relevant.

I solved this myself, and thought maybe someone else might have use from my findings. I solved it like this:
In b/main.qbs I created property name2 & path2 to hold the local name & path like so:
import "../a/imported.qbs" as Imported
Imported {
property string path2:path
property string name2:name
}
and in a/imported.qbs I use the properties like this:
Product{
name:{
console.info("I was imported from" + name2 + " (" + path2 + ")");
return "imported"
}
}

Related

How do I bundle and read files within my extension?

I'm learning how to create vscode extensions and I'm simply trying to emulate a template plugin to be used internally within my company. I'd like to store the template in a file within the extension and then read the contents from that file and output it to the active window. So given the following example directory structure of the extension (other files omitted for brevity):
workspace/
|- templates/
| |- template1.yaml
| |- template2.yaml
|- extension.js
For the command that I'm registering, I'd simply like to read from one of those files and send it to the window as a snippet, but I don't know how to find the path to that folder
// extension.js
function activate(context) {
context.subscriptions.push(
vscode.commands.registerCommand("xxx.my-command"), function() {
let path = // ???/templates/template1.yaml
fs.readFile(path, (err, data) => {
let snippet = new vscode.SnippetString(data);
vscode.window.activeTextEditor.insertSnippet(snippet);
}
})
})
)
}
When I try to use relative paths to that templates folder, it appears to be relative to the VSCode installation. I looked around TextDocument provider etc but all of the examples were relevant to using the active editor as the document. How can I include files with my extension and access the contents of those files like this?
You should use context.asAbsolutePath, which by documentation says:
/**
* Get the absolute path of a resource contained in the extension.
*
* *Note* that an absolute uri can be constructed via {#linkcode Uri.joinPath} and
* {#linkcode ExtensionContext.extensionUri extensionUri}, e.g. `vscode.Uri.joinPath(context.extensionUri, relativePath);`
*
* #param relativePath A relative path to a resource contained in the extension.
* #return The absolute path of the resource.
*/
asAbsolutePath(relativePath: string): string;
For instance
const path = context.asAbsolutePath("templates/template1.yaml");
I also suggest you to avoid using Node's fs. Instead, use workspace.fs whenever possible. It will enable your extension to work on Remotes and Web, when necessary. More details here https://code.visualstudio.com/api/extension-guides/virtual-workspaces#review-that-the-extension-code-is-ready-for-virtual-resources
Hope this helps
I found that I could actually do a couple different things:
const path = require('path')
let templatePath = path.resolve(__dirname, './templates/template1.yaml');
But also as Mark suggested in the comments, using the extension context also provides that path:
/**
* #param {vscode.ExtensionContext} context
*/
function activate(context) {
let templatePath = context.extensionPath + '/templates/template1.yaml';
}
I went with the latter since it is being injected by the runtime which seemed better to me if not simpler. Thanks Mark!

How can the Repast file sink filename be set programmatically?

Does anybody know if there is a simple way to make the filename element path of an file sink variable according to one field in the model?
So instead of using a fix path like :
fixed_path/filename.csv
{variable_path}/filename.csv
The attached ModelInitializer shows how to do this. I also copied the code below in case attachments doesn’t go through. To enable the ModelInitializer, you need to add the following to the scenario.xml file:
<model.initializer class="PredatorPrey.MyInitializer" />
I tested this in the Predator Prey demo so you should change the class package name. In the ModelInitializer example, you need to specify the root context ID which is the same as the context ID in the context.xml file. And you should specify the variable output folder name. This example requires a file name to be specified in the file sink as you would normally do and it inserts the variable path. On caveat is that the variable folder path will be saved in the scenario if the scenario is saved in the GUI, however this code will check for any existing path and simply replace the path with the outputFolder string. So you should put the entire path in the outputFolder string and not just part of it, or change the code behavior as needed.
package PredatorPrey;
import java.io.File;
import repast.simphony.data2.engine.FileSinkComponentControllerAction;
import repast.simphony.data2.engine.FileSinkDescriptor;
import repast.simphony.engine.controller.NullAbstractControllerAction;
import repast.simphony.engine.environment.ControllerAction;
import repast.simphony.engine.environment.RunEnvironmentBuilder;
import repast.simphony.engine.environment.RunState;
import repast.simphony.scenario.ModelInitializer;
import repast.simphony.scenario.Scenario;
import repast.simphony.util.collections.Tree;
public class MyInitializer implements ModelInitializer {
#Override
public void initialize(final Scenario scen, RunEnvironmentBuilder builder) {
scen.addMasterControllerAction(new NullAbstractControllerAction() {
String rootContextID = "Predator Prey";
String outputFolder = "testoutfolder";
#Override
public void batchInitialize(RunState runState, Object contextId) {
Tree<ControllerAction> scenarioTree = scen.getControllerRegistry().getActionTree(rootContextID);
findFileSinkTreeChildren(scenarioTree, scenarioTree.getRoot(), outputFolder);
// Reset the scenario dirty flag so the changes made to the file sink
// descriptors don't prompt a scenario save in the GUI
scen.setDirty(false);
}
});
}
public static void findFileSinkTreeChildren(Tree<ControllerAction> tree,
ControllerAction parent, String outputFolder){
// Check each ControllerAction in the scenario and if it is a FileSink,
// modify the output path to include the folder
for (ControllerAction act : tree.getChildren(parent)){
if (act instanceof FileSinkComponentControllerAction){
FileSinkDescriptor descriptor = ((FileSinkComponentControllerAction)act).getDescriptor();
String fileName = descriptor.getFileName();
// remove any prefix directories from the file name
int lastSeparatorIndex = fileName.lastIndexOf(File.separator);
// Check for backslash separator
if (fileName.lastIndexOf('\\') > lastSeparatorIndex)
lastSeparatorIndex = fileName.lastIndexOf('\\');
// Check for forward slash operator
if (fileName.lastIndexOf('/') > lastSeparatorIndex)
lastSeparatorIndex = fileName.lastIndexOf('/');
if (lastSeparatorIndex > 0){
fileName = fileName.substring(lastSeparatorIndex+1, fileName.length());
}
descriptor.setFileName(outputFolder + File.separator + fileName);
}
else findFileSinkTreeChildren(tree, act, outputFolder);
}
}
}

requiring lodash modules with webpack

I used to use lodash.js without any packaging like below:
if (_.isFunction(myFunc)) { ... }
Recently, I started using webpack. Now, it seems many functions such as isFunction are not part of the core module. So, the following works:
var _ = require("lodash/core");
var _isFunction = require("lodash/isFunction");
However, the above changes the syntax when I used lodash without webpack (no dot). Should I require like below:
_.isFunction = require("lodash/isFunction")
so, that to maintain the same syntax?
When you do something like the following, you import everything under one big lodash object:
var _ = require('lodash');
_ (or whatever var you choose) will be filled with a bunch of functions:
_ = {
isX: function...
isY: function...
// ... etc
}
Ie: it brings everything in.
When you do the following, it will import only the required module directly into the variable:
var anynameX = require('lodash/isX');
var anynameY = require('lodash/isY');
anynameX and anynameY can be anything.
In other words:
_.isX === anynameX;
_.isY === anynameY;
So to answer your last question, you could do:
_.anynameX = require('lodash/isX');
but only if _ already exists (and isn't frozen), for example:
var _ = {};
_.anynameX = require('lodash/isX');

Issue creating a single .d.ts when using external modules

I'm developing an NPM package using typescript. Within this package the TS files are setup as external modules. The compiler won't generate a single .d.ts for external modules. I'm trying to concat all tsc generated type definitions into a single .d.ts for the entire package.
I'm having issues laying out the single .d.ts file (following a similar approach to that used in grunt-dts-bundle). The condensed example below captures my issue.
Given this external module declaration and test file:
test.d.ts :
declare module "ExternalWrapper" {
export import Foo = require("FooModule");
}
declare module "FooModule" {
class Foo {
name: string;
}
export = Foo;
}
test.ts:
import externalWrapper = require( 'ExternalWrapper' );
var t = new externalWrapper.Foo();
Running tsc test.ts test.d.ts -m commonjs produces this error: TS2083: Invalid 'new' expression.
If you change 'test.ts' to look like this, importing 'FooModule' directly:
import Foo = require( "FooModule" );
var t = new Foo();
It compiles fine.
The compiler understands the type externalWrapper.Foo however it doesn't seem to represent it as the same type FooModule.Foo. There is something I'm not getting about how the compilers handles modules that are exported via 'export import'.
Failing the above I'll probably look to manually creating the .d.ts :(
Any help appreciated.
You are probably missing a reference tag:
/// <reference path="test.d.ts"/>
It works :
You should be able to fix this by modifying your .d.ts file to resemble the following:
declare module "ExternalWrapper" {
import FooModule = require("FooModule");
export var Foo: typeof FooModule;
}
declare module "FooModule" {
class Foo {
name: string;
}
export = Foo;
}
With the export import syntax the compiler was assuming you were exporting an instance of Foo, not Foo itself... a little quirky.

Android studio | Dependency Management

Can anyone suggest, how can we add a dependency at build time in android gradle based on some condition like:
dependencies{
if(someCondition){
// add dependency
}
}
Thanks in advance!!
I found a solution for this:
Step1: Declare a boolean variable in gradle at root level.
like: def someDependencyEnabled = true //This could be dynamically set.
Step2: Using this boolean variable we can apply a check like:
if(someDependencyEnabled){
//Add some dependency
}
else
{
//Add some other dependency
}
Step3: Define Different source set for different situations:
android.sourceSets {
main {
java.srcDirs = ['src/main/java', someDependencyEnabled ? 'src/dependency_enabled_src' : 'src/dependency_disabled_src']
}
}
where:
'src/main/java' : is the common src file which contain common code.
'src/dependency_enabled_src': is the source folder that contain dependency specific code. which is further used by 'src/main/java'.
'src/dependency_disabled_src': is the source folder that contain alternate code when particular dependency is disabled.
In my case I wrote same name classes, methods & package name in both folders (dependency_enabled & dependency_disabled src) and wrote methods with desired implementation in dependency_enabled_src & empty methods for dependency_disabled_src.