Is it possible to use constructions like QMap< QString, boost::multi_index_container<...> >?
On the one hand, we have private:
BOOST_COPYABLE_AND_MOVABLE(multi_index_container)
in the containers declaration. It should tell us not to put multi_index_container<> into other stl-like container.
On the other hand, such construction
QMap< QString, boost::multi_index_container<...> > _map;
map.insert("bla-bla", container1);
...
auto tmp = _map.value(QString("bla-bla")).get<keyVal>();
//keyVal corresponds to one for the multi_index_container instance
is compiled well with Visual Studio 2012 (+update4 + boost v1.55 + qt v4.8.5).
Experimentally it was discovered that:
auto tmp = _map.value(QString("bla-bla")).get<keyVal>();
makes tmp to handle deleted data.
while
auto tmp = _map.value(QString("bla-bla"));
auto tmp_1 = tmp.get<keyVal>();
leaves tmp_1 with valid data.
Does anybody know what is the proper treatment with boost::multi_index_container<> if we need to put it in another container?
Are there any differences for Qt5.3?
As you can see in the docs for QMap:
const T QMap::value(const Key & key, const T & defaultValue = T()) const
The value is returned by value, not by reference. Besides being very inefficient for large values (such as multi index containers, maybe?) it also returns a temporary.
Now, get<keyVal>(); does return a reference to the first index, but it's the one that belongs to the temporary, which dies at the end of the containg full-expression.
To get a modifiable reference, use
T & QMap::operator[](const Key & key)
Now you can:
auto& tmp = _map[QString("bla-bla")].get<keyVal>();
Note the &.
Adding to #sehe's answer on how to retrieve references rather than temporary values, boost::multi_index_container is copyable and movable. This BOOST_COPYABLE_AND_MOVABLE macro you refer to has to be placed on the class private section (as specified here), but that does not affect visibility of copy/movement ctors. Moral of the story: consult docs before diving into the code.
In my particular case, the problem was that compiler used const T operator[](const Key & key) const instead of T & operator[](const Key & key) because the method of the class was a const one and the map was a field of the class.
Related
I'm trying to use SequenceReader<T> in .Net Core Preview 8 to parse Guacamole Protocol network traffic.
The traffic might look as follows:
5.error,14.some text here,1.0;
This is a single error instruction. There are 3 fields:
OpCode = error
Reason = some text here
Status = 0 (see Status Codes)
The fields are comma delimited (semi-colon terminated), but they also have the length prefixed on each field. I presume that's so that you could parse something like:
5.error,24.some, text, with, commas,1.0;
To produce Reason = some, text, with, commas.
Simple comma delimited parsing is simple enough to do (with or without SequenceReader). However, to utilise the length I've tried the following:
public static bool TryGetNextElement(this ref SerializationContext context, out ReadOnlySequence<byte> element)
{
element = default;
var start = context.Reader.Position;
if (!context.Reader.TryReadTo(out ReadOnlySequence<byte> lengthSlice, Utf8Bytes.Period, advancePastDelimiter: true))
return false;
if (!lengthSlice.TryGetInt(out var length))
return false;
context.Reader.Advance(length);
element = context.Reader.Sequence.Slice(start, context.Reader.Position);
return true;
}
Based on my understanding of the initial proposal, this should work, though also could be simplified I think because some of the methods in the proposal make life a bit easier than that which is available in .Net Core Preview 8.
However, the problem with this code is that the SequenceReader does not seem to Advance as I would expect. It's Position and Consumed properties remain unchanged when advancing, so the element I slice at the end is always an empty sequence.
What do I need to do in order to parse this protocol correctly?
I'm guessing that .Reader here is a property; this is important because SequenceReader<T> is a mutable struct, but every time you access .SomeProperty you are working with an isolated copy of the reader. It is fine to hide it behind a property, but you'd need to make sure you work with a local and then push back when complete, i.e.
var reader = context.Reader;
var start = reader.Position;
if (!reader.TryReadTo(out ReadOnlySequence<byte> lengthSlice,
Utf8Bytes.Period, advancePastDelimiter: true))
return false;
if (!lengthSlice.TryGetInt(out var length))
return false;
reader.Advance(length);
element = reader.Sequence.Slice(start, reader.Position);
context.Reader = reader; // update position
return true;
Note that a nice feature of this is that in the failure cases (return false), you won't have changed the state yet, because you've only been mutating your local standalone clone.
You could also consider a ref-return property for .Reader.
I am writing some code where I have multiple dictionaries for my data. The reason being, I have multiple core objects and multiple smaller assets and the user must be able to choose a smaller asset and have some function off in the distance run the code with the parent noted.
An example of one of the dictionaries: (I'm working in ROBLOX Lua 5.1 but the syntax for the problem should be identical)
local data = {
character = workspace.Stores.NPCs.Thom,
name = "Thom", npcId = 9,
npcDialog = workspace.Stores.NPCs.Thom.Dialog
}
local items = {
item1 = {
model = workspace.Stores.Items.Item1.Main,
npcName = "Thom",
}
}
This is my function:
local function function1(item)
if not items[item] and data[items[item[npcName]]] then return false end
end
As you can see, I try to index the dictionary using a key from another dictionary. Usually this is no problem.
local thisIsAVariable = item[item1[npcName]]
but the method I use above tries to index the data dictionary for data that is in the items dictionary.
Without a ton of local variables and clutter, is there a way to do this? I had an idea to wrap the conflicting dictionary reference in a tostring() function to separate them - would that work?
Thank you.
As I see it, your issue is that:
data[items[item[npcName]]]
is looking for data[“Thom”] ... but you do not have such a key in the data table. You have a “name” key that has a “Thom” value. You could reverse the name key and value in the data table. “Thom” = name
I am using qt's undo framework , which use qundocommand to do some application support undo.
Is there an easy way I can use to save those qundocommand to a file and reload it?
There's no built-in way. I don't think it's very common to save the undo stack between sessions. You'll have to serialize the commands yourself by iterating through the commands on the stack, and saving each one's unique data using QDataStream. It might look something like this:
...
dataStream << undoStack->count(); // store number of commands
for (int i = 0; i < undoStack->count(); i++)
{
// store each command's unique information
dataStream << undoStack->command(i)->someMemberVariable;
}
...
Then you would use QDataStream again to deserialize the data back into QUndoCommands.
You can use QFile to handle the file management.
Use Qt's serialization as described here:
Serialization with Qt
Then within your QUndoCommands you can use a temp file to write the data to it:
http://qt-project.org/doc/qt-4.8/qtemporaryfile.html
However this might cause you an issue since each file is kept open and so on some platforms (Linux) you may run out of open file handles.
To combat this you'd have to create some other factory type object which handles your commands - then this could pass in a reference to a QTemporaryFile automatically. This factory/QUndoCommand care taker object must have the same life time as the QUndoCommands. If not then the temp file will be removed from disk and your QUndoCommands will break.
The other thing you can do is use QUndoCommand as a proxy to your real undo command - this means you can save quite a bit of memory since when your undo command is saved to file you can delete the internal pointer/set it to null. Then restore it later.
Here's a PyQt solution for serializing/pickling QUndoCommands. The tricky part was getting the parent to call __init__ first, then the children. This method relies on all the children's __setstate__ to be called before the parent's, which happens upon pickling as children are returned in the parent's __getstate__.
class UndoCommand(QUndoCommand):
"""
For pickling
"""
def __init__(self, text, parent=None):
QUndoCommand.__init__(self, text, parent)
self.__parent = parent
self.__initialized = True
# defined and initialized in __setstate__
# self.__child_states = {}
def __getstate__(self):
return {
**{k: v for k, v in self.__dict__.items()},
'_UndoCommand__initialized': False,
'_UndoCommand__text': self.text(),
'_UndoCommand__children':
[self.child(i) for i in range(self.childCount())]
}
def __setstate__(self, state):
if hasattr(self, '_UndoCommand__initialized') and \
self.__initialized:
return
text = state['_UndoCommand__text']
parent = state['_UndoCommand__parent'] # type: UndoCommand
if parent is not None and \
(not hasattr(parent, '_UndoCommand__initialized') or
not parent.__initialized):
# will be initialized in parent's __setstate__
if not hasattr(parent, '_UndoCommand__child_states'):
setattr(parent, '_UndoCommand__child_states', {})
parent.__child_states[self] = state
return
# init must be called on unpickle-time to recreate Qt object
UndoCommand.__init__(self, text, parent)
for child in state['_UndoCommand__children']:
child.__setstate__(self.__child_states[child])
self.__dict__ = {k: v for k, v in state.items()}
#staticmethod
def from_QUndoCommand(qc: QUndoCommand, parent=None):
if type(qc) == QUndoCommand:
qc.__class__ = UndoCommand
qc.__initialized = True
qc.__parent = parent
children = [qc.child(i) for i in range(qc.childCount())]
for child in children:
UndoCommand.from_QUndoCommand(child, parent=qc)
return qc
We're looking into refining our User Groups in Dynamics AX 2009 into more precise and fine-tuned groupings due to the wide range of variability between specific people within the same department. With this plan, it wouldn't be uncommon for majority of our users to fall user 5+ user groups.
Part of this would involve us expanding the default length of the User Group ID from 10 to 40 (as per Best Practice for naming conventions) since 10 characters don't give us enough room to adequately name each group as we would like (again, based on Best Practice Naming Conventions).
We have found that the main information seems to be obtained from the UserGroupInfo table, but that table isn't present under the Data Dictionary (it's under the System Documentation, so unavailable to be changed that way by my understanding). We've also found the UserGroupName EDT, but that is already set at 40 characters. The form itself doesn't seem to restricting the length of the field either. We've discussed changing the field on the SQL directly, but again my understanding is that if we do a full synchronization it would overwrite this change.
Where can we go to change this particular setting, or is it possible to change?
The size of the user group id is defined as as system extended data type (here \System Documentation\Types\userGroupId) and you cannot change any of the properties including the size 10 length.
You should live with that, don't try to fake the system using direct SQL changes. Even if you did that, AX would still believe that length is 10.
You could change the SysUserInfo form to show the group name only. The groupId might as well be assigned by a number sequence in your context.
I wrote a job to change the string size via X++ and it works for EDTs, but it can't seem to find the "userGroupId". From the general feel of AX I get, I'd be willing to guess that they just have it in a different location, but maybe not. I wonder if this could be tweaked to work:
static void Job9(Args _args)
{
#AOT
TreeNode treeNode;
Struct propertiesExt;
Map mapNewPropertyValues;
void setTreeNodePropertyExt(
Struct _propertiesExt,
Map _newProperties
)
{
Counter propertiesCount;
Array propertyInfoArray;
Struct propertyInfo;
str propertyValue;
int i;
;
_newProperties.insert('IsDefault', '0');
propertiesCount = _propertiesExt.value('Entries');
propertyInfoArray = _propertiesExt.value('PropertyInfo');
for (i = 1; i <= propertiesCount; i++)
{
propertyInfo = propertyInfoArray.value(i);
if (_newProperties.exists(propertyInfo.value('Name')))
{
propertyValue = _newProperties.lookup(propertyInfo.value('Name'));
propertyInfo.value('Value', propertyValue);
}
}
}
;
treeNode = TreeNode::findNode(#ExtendedDataTypesPath);
// This doesn't seem to be able to find the system type
//treeNode = treeNode.AOTfindChild('userGroupId');
treeNode = treeNode.AOTfindChild('AccountCategory');
propertiesExt = treeNode.AOTgetPropertiesExt();
mapNewPropertyValues = new Map(Types::String, Types::String);
mapNewPropertyValues.insert('StringSize', '30');
setTreeNodePropertyExt(propertiesExt, mapNewPropertyValues);
treeNode.AOTsetPropertiesExt(propertiesExt);
treeNode.AOTsave();
info("Done");
}
N.B. Keep in mind the difference between key code and character code. For example, the number 1 (one) and the character ! (bang) both have the same key code but different character codes. Likewise, the number 7 from the row of numbers and the number 7 from the numpad have different key codes but the same character codes.
I'm programming a music rhythm game in Adobe Flex and would like to bind keyboard keys. This isn't a problem, but I certainly would have a problem, say, setting the default keys to A, S, D, and F and telling the user that this is the case.
If you take a look at the documentation for flash.ui.Keyboard, you'll see that there are constants for keyboard keys to key codes. However, these are only available in Adobe AIR and not the browser. This makes sense since not all operating systems and keyboards are alike (or present!), so key codes can vary.
So, how can I assign default keys that have meaning instead of picking key codes and praying?
My only sane thought is to store the character codes for the key bindings and then provide an character code to String mapping so I can tell the user what to press. However, my gut tells me that this will break in subtle or not-so-subtle ways. Like CAPSLOCK.
Thanks.
Update: I am currently using radekg's answer, but I still think that this will break easily. I would feel more comfortable with some persuasion that this is correct.
according to Flash 8 documentation you can simply rely on ASCII codes. Take a look at these topics of the Flash 8 documentation:
http://livedocs.adobe.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Flash_MX_2004&file=00001113.html
http://livedocs.adobe.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Flash_MX_2004&file=00001115.html#71579
http://livedocs.adobe.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Flash_MX_2004&file=00001116.html#71709
http://livedocs.adobe.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Flash_MX_2004&file=00001114.html#71525
As far as I'm aware of all modern operating systems use standard ASCII. These codes have not changed since Flash 5 era. To compare letters if you don't want to rely on ASCII codes:
private function compareChar(code:Number):void {
if ( "a" == String.fromCharCode( code ).toLowerCase() ) {
trace("A pressed");
} else {
trace("You pressed " + String.fromCharCode(code));
}
}
...
compareChar(65); // 65 is A
compareChar(96); // 96 is numpad 0
However I think you can rely on ASCII codes.
Hope this helps.
Radekg is mostly correct.
Flash has a built in Class flash.ui.KeyLocation with four static properties: LEFT, RIGHT, NUM_PAD, STANDARD. This means that you can have a definitive idea which key has been pressed, even if the keyboard has been remapped. If you this in combination with String.fromCharCode, you should be able to solve this problem rather neatly.
Your final code might look like:
import flash.ui.KeyLocation;
import flash.events.KeyboardEvent;
function handleKeyboardEvent( event:KeyboardEvent )
{
// This will work for a majority of the keys.
var key:String = String.fromCharCode( event.charCode ).toLowerCase();
// Use strict comparison
if( event.keyLocation !== KeyLocation.STANDARD )
{
// The key is a number, then it needs to be re-identified.
if( event.keyLocation == KeyLocation.RIGHT ) key = "r" + key;
if( event.keyLocation == KeyLocation.LEFT ) key = "l" + key;
if( event.keyLocation == KeyLocation.NUM_PAD) key = "n" + key;
}
switch( key )
{
case "r1":
// Do something with the one which is not on the keypad.
break;
case "n.":
// Do something with the number pad's period.
break;
case "n":
// Do something with the letter N.
break;
}
}
I will admit, I am not certain what will happen with String.fromCharCode and control keys (F1, Alt, Ctrl, etc), but the KeyboardEvent does support event.shiftKey, event.ctrlKey, event.altKey