IUP, button, tree, matrix - c

1)
I try to load ico image to IUPbutton but with no success.
After linking IM dll's and add proper header this is my approach:
Ihandle *btn1, *btn2;
Ihandle* img1;
btn1 = IupButton("", NULL);
IupSetAttribute(btn1, "MINSIZE", "24x24");
btn2 = IupButton("", NULL);
IupSetAttribute(btn2, "MINSIZE", "24x24");
img1 = IupImage(16, 16, IupLoadImage("icons\\home_16x16.ico"));
IupSetAttribute(btn1, "IMAGE", "img1");
frame = IupHbox(btn1, btn2, NULL);
dlg = IupDialog(IupHbox(mat, IupVbox(frame, tree, NULL), NULL));
IUP don't report any error but image don't appear on the button btn1.
How to load picture from file to a button in RGBA mode?
2)
I fill IupTree with data from sqlite database in following order: 'Name' (which is root) and then about 170 branches which have 1-10 leafs. VALUE is set to 0 and 'Name' is selected.
How can I get with code expanded tree to first branches like when I doubleclick to 'Name'?
I try EXPANDALL attribute but then all leaf's are expanded too what is not wanted.
3)
How can I get IUPtree item 'id' in k_any callback f. e. when press ENTER key?
4)
How can I get IUPtree item text from 'id' in executeleaf and branchopen callbacks?
5)
How can I loop through IUPtree to get id, text, sort of item (branch/leaf)?
6) Is here a way on IUPmatrix to catch keyUP or keyRELEASED event like we get keyPRESS in K_ANY?

1) Pay more attention to the data type of each function. Notice that IupLoadImage already returns an Ihandle. So instead of:
img1 = IupImage(16, 16, IupLoadImage("icons\\home_16x16.ico"));
you should do this:
img1 = IupLoadImage("icons\\home_16x16.ico");
Also if you do this:
IupSetAttribute(btn1, "IMAGE", "img1");
you are specifying a string, you must somehow associate the string "img1" to the Ihandle img1. They are two very different things. Check the IupImage documentation. Or you do:
IupSetHandle("img1", img1);
IupSetAttribute(btn1, "IMAGE", "img1");
Or a better way:
IupSetAttributeHandle(btn1, "IMAGE", img1);
2) Have you try to expand only the branch you want expanded? Check the STATEid attribute on the IupTree documentation.
3) What you want is to the the item that has the focus. So get the VALUE attribute of the IupTree. Notice that the Enter key will trigger the executeleaf callback which already has the item id.
4) Check the TITLEid attribute in the documentation.
5) A tip, when setting/getting attributes of a IupTree, IupMatrix or IupList, you can use:
IupSetAttribute(ih, "TITLE3", "My Title");
or
IupSetAttributeId(ih, "TITLE", 3, "My Title");
6) As I told you before, IupMatrix inherits from IupCanvas, so you must also check for the IupCanvas callbacks. Check the IupMatrix callbacks documentation, at the end there is an explanation about the IupCanvas callbacks.

Related

Is there a way to use/get the value from a current entry window

I'm trying to get the variable that's entered in an entry widget on the Return key pressed event, but struggling a bit. What I have tried has always produced a blank result.
This code may look messy and hap-hazard, but it's only going to be a template that I'll be using on a current project!
I've tried that many things to get it to work, I can't remember what I have tried!
from collections import OrderedDict
try:
import tkinter as tk
except:
import Tkinter as tk
root = tk.Tk()
labelLIST = OrderedDict([
('Temp ID', 'tempID'),
('PO Number', "poNumber"),
('Reference', "reference"),
('Cut/Sample Date', "csDate"),
('Cut Number', "cut")
])
i = 0
e_loops = len(labelLIST)
print (e_loops)
def bval1(event=None):
for i in range(e_loops):
print (entries[i].get())
entries[0].delete(0, tk.END)
entries[0].insert(0, 'DISABLED')
entries[0].configure(state='disabled')
def bval2():
entries[0].configure(state='normal')
for i in range(e_loops):
entries[i].delete(0, tk.END)
entries[0].focus()
def onClick(event):
ent = event.widget # event.widget is the widget that called the event
print(ent.cget("text")) # Print the text for the selected button
event.widget.tk_focusNext().focus()
def enterEV(event):
# print(entries[].get())
event.widget.tk_focusNext().focus()
entries = []
for key, value in labelLIST.items():
label = tk.Label(root, text=key)
label.grid(row=i, column=0, sticky="ew", padx=1, pady=1)
entry = tk.Entry(root, width=10)
entry.grid(row=i, column=1, sticky="ew", padx=5, pady=5)
if value == "cut":
entry.bind('<Return>', bval1)
else:
# entry.bind('<Return>', enterEV)
entry.bind('<Return>', onClick)
entries.append(entry)
i = i+1
button = tk.Button(root, text="Submit", command=bval1)
button.grid(row=0, column=2, columnspan=9, sticky="ew")
button = tk.Button(root, text="Clear", command=bval2)
button.grid(row=1, column=2, columnspan=9, sticky="ew")
entries[0].focus()
tk.mainloop()
When enter/return is pressed, I want the value that is the entry box to be printed to terminal via the onClick event. But the output is always empty.
def onClick(event):
ent = event.widget # event.widget is the widget that called the event
print(ent.cget("text")) # Print the text for the selected button
event.widget.tk_focusNext().focus()
You don't use the text attribute to get the value in an Entry widget. Using cget("text") returns the value for the textvariable attribute. Since you haven't set that attribute, it will always be the empty string.
Instead, you need to call the get method:
print(ent.get())

How to use Group by query in laravel?

this is how the data is displayed but i want
Rhugveda desai -> flowers,Sarees,Prasad
In my application i need to use group by clause . But i am getting a syntax error.Also, What should i do if i want quantity column to be multiplied by amount to get the total? My tables are inkind and inkind_items, where inkind.id is foreign key in inkind_items table as inkind_id.
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #11
of SELECT list is not in GROUP BY clause and contains nonaggregated
column
my inkind_items tabel is inkind_items
my inkind table is inkind
My query is:
$inkinds = DB::table('inkind')
->join('inkind_items', 'inkind.id', '=', 'inkind_items.inkind_id')
->select('inkind.*', 'inkind_items.*')
->groupBy('inkind_items.inkind_id')
->get();
Try using group_concat()
$inkinds = DB::table('inkind')
->join('inkind_items', 'inkind.id', '=', 'inkind_items.inkind_id')
->select('inkind.*', DB::raw('group_concat(inkind_items.name) as items'))
->groupBy('inkind_items.inkind_id')
->get();
Here I'm assuming inkind have field name and inkind_items has fields items.
You can use Laravel collection methods for that.
Just call:
$inkinds->groupBy('inkind_id');
after ->get(). Considering that inkind_id is unique column for both tables
Hi. You asked another question earlier today (about displaying an input when a particular checkbox is checked) but deleted it before I submitted my answer, so I thought I would paste the answer here instead:
Just to get you started, here is an explanation of how to use
addEventListener and createElement to achieve your desired result.
If any part of it is still unclear after studying the code and the
accompanying comments, please search for the name of the still-unclear function on
MDN.
(For example, https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName.)
// Sets `box1` to refer to the first element on the page with the class "box".
const box1 = document.getElementsByClassName("box")[0];
// Sets `container` to be the element whose id attribute has the value "container".
// (This is where our new input element, inside a new label element, will be added.)
const container = document.getElementById("container");
// Begins listening for clicks. From now on, whenever the user clicks anywhere
// on the page, our listener will call the `noticeClick` function.
document.addEventListener("click", noticeClick);
function noticeClick(event){
// Because this function's name is the second argument in
// the call to `document.addEventListener`, above, it is
// automatically called every time a 'click' event happens on the
// page (and it automatically receives that event as an argument.)
// The "target" of the event is whatever the user clicked on.
// So we set the variable `targ` to refer to this target, and we check whether:
// 1) the clicked target is our checkbox,
// 2) this click caused the checkbox to gain the "checked" attribute, and
// 3) we have not already given the checkbox the "added" class
const targ = event.target;
if(targ.id == "box1" && targ.checked && !targ.classList.contains("added")){
// If all three conditions are met, we...
// ...set two variables, `label` and `val`
const label = event.target.id;
const val = event.target.value;
// ...call the `createInput` function, passing these variables as its two arguments
createInput(label, val);
// ...give the checkbox the "added" class (so we can avoid accidentally adding it again)
targ.classList.add("added");
}
}
function createInput(newLabel, newValue){
// When the user has checked our checkbox, the `noticeClick` function
// will call this function, which receives two arguments (which we can
// see, by examining the `noticeClick` function, are two strings: the
// `id` attribute of box1 and the `value` attribute of box1.)
// We use `document.creatElement` to create an `input` element and a
// `label` element, and `document.createTextNode` to set some text
// to be used in the label (using the "newLabel" argument.)
const myInput = document.createElement("input");
const myLabel = document.createElement("label");
const myLabelText = document.createTextNode(newLabel + " ");
// We set our new `input` element's value using the "newValue" argument.
myInput.value = newValue;
// We use `appendChild` to put both the text and the input element
// inside the label, and to put the label inside `container`.
myLabel.appendChild(myLabelText);
myLabel.appendChild(myInput);
container.appendChild(myLabel);
}
// This process can be applied to multiple checkboxes on the same page
// by adding a loop inside the `noticeClick` function, where the string
// "box1" should be replaced with a variable that can refer to the id of a
// different checkbox's `id` for each iteration of the loop.
<label>
<input type="checkbox" id="box1" class="box" value="value1" />
Label for box1
</label>
<hr />
<div id="container"></div>

ngTagsInput- what is run when selecting one of the options displayed by autocomplete?

I am working on an AngularJS application, and have a dialog which is used to update what is displayed on one of the widgets on a particular page.
The widget is a table, and I want to allow the user to display different data types/ HTML elements in particular cells of the table.
As it currently stands, the cells will display text, a button, or a 'tag' which is a variable taken from the system, and displayed as a particular element using the ngTagsInput library. As the user types into the text input field, the autocomplete feature displays a list of 'tags' that match what has been typed so far- when the user clicks one of these tags in the list, that is when it is then displayed as a tag in the table widget (if they just type the full name of the tag without selecting it from the autocomplete list, it is just displayed as text).
I have made some changes so that when the first character that the user types is a :, the autocomplete list should show a list of the various pages of the application, for which a button linking to that page will be added to the table (i.e. typing page1 would just show the text "page1" in the table cell, but typing :, and selecting 'page1' from the autocomplete list would display a button linking to page1). This functionality currently works as expected,.
I now want to be able to add multiple buttons to a single table cell (assuming that the user inputs the tags into the text field in the dialog in the correct format). The format to do this will be the same as for one button, but with a ; separating each of the individual buttons- for example, to add buttons for page1 & page2 to the same table cell, the user should just type: :page1;page2.
The autocompleteTagsFilter() function, which is what displays the list of available tags/ pages based on what the user has typed so for (i.e. filters the list of available options as the user continues typing) is defined with:
$scope.autocompleteTagsFilter = function(query) {
if (query.startsWith(":")) {
// Split the 'query' search string on ':', to use only the string
var buttonsQuery = query.substring(1);
if (!buttonsQuery && lastTagQryKw) {
buttonsQuery = lastTagQryKw;
}
/*check whether the buttonsQuery variable contains a ';' - if it does, split it */
if(buttonsQuery.includes(';')) {
//console.log("buttonsQuery includes ; - ", buttonsQuery);
var btnsToDisplay = buttonsQuery.split(";");
console.log("btnsToDisplay: ", btnsToDisplay);
}
// Declare variables to be used in 'for' loop
var userPages = pagesPresets;
var page;
var result = [];
// 'For' loop should iterate through the list of user pages,
// and remove path, so that only the page name is shown
for (page in userPages) {
page = userPages[page];
// If the page key starts with 'buttonsQuery', and its length
// is greater than 6 (i.e. just 'pages/' shouldn't be displayed)
// add the page to the list of pages to be displayed.
if (page.key.startsWith(buttonsQuery) && page.key.length > 6) {
result.push(page.key);
//console.log("result- after result.push(page.key): ", result);
} else {
//console.log("userPages: ", userPages);
}
};
for (btn in btnsToDisplay) {
console.log("btn: ", btnsToDisplay[btn]);
result.push(btnsToDisplay[btn]);
console.log("button added to result: ", result);
if (result.length > 0) {
lastTagQryKw = query;
}
// Return the list of pages that match what the user has typed
//console.log("RESULT (when query.startsWith(':') is true) is: ", result);
return result;
// Otherwise, if the user types something that does not start with ':',
//then it should be a tag- search for tags that match this term
} else {
if (!query && lastTagQryKw) {
query = lastTagQryKw;
}
var result = Object.keys(fxTag.getTags()).filter(function(name) {
return name.indexOf(query.toLowerCase()) !== -1;
});
if (result.length > 0) {
lastTagQryKw = query;
}
console.log("RESULT (when query.startsWith(':') is false) is: ", result);
return result;
}
};
As I type, if I start typing with a :, then the browser console displays a list of pages that I could add a button for:
RESULT (when query.startsWith(':') is true) is: (4) ["pages/userpage1", "pages/pagetitle", "pages/userpage2", "pages/auth"]
If I select one of these buttons, that button is correctly added, and when I click the 'Preview' button on the dialog, the dialog closes and the page shows the table with the working button correctly added to the table cell. The console also shows the output:
tag is only one tag: {tag: "pages/auth"}
which comes from the function onAddingTagItem()
However, if I continue typing, rather than selecting one of the buttons shown by the autocomplete, and type out two buttons, i.e.
:pages/userpage1;pages/userpage2
then rather than displaying two buttons, the table cell just displays the text, i.e :pages/userpage1;pages/userpage2.
and I get the console output:
value of tags: (2) [":pages/userpage1", "pages/userpage2"]
The same onAddingTagItem() function is called in both cases, only it runs the if instead of the else when the text entered by the user contains a ;. This function is defined with:
$scope.onAddingTagItem = function(tag) {
if(tag.tag.includes(";")) {
var tags = tag.tag.split(";");
console.log("value of tags: ", tags);
angular.forEach(tags, function(tag, key) {
if(tag.startsWith(":")) {
tag = tag.split(":")[1];
}
angular.extend(tag, toTagItemObj(tag));
})
} else {
console.log("tag is only one tag: ", tag);
}
return true;
};
So, as I understand, it should be returning the tags whether there are one or several of them, because it returns true whether the if or the else is run.
Given that this function always returns true, whether it's the if or the else that has been run, why is it that a button is only displayed when I click an option from the autocomplete list, and not when typing out a button in full?
How can I ensure that the text entered will be displayed as a button when it meets the criteria (starts with a :), even if it's not selected from the autocomplete list, or enable selection of multiple items from the autocomplete list?

How do I add a combobox to first column cells in QtRuby?

I've been trying to add a simple combobox with four items to a stupid table widget cell and I still can't get it placed in the correct row and column. The best I could get was to make it show up only if I tell the combobox its parent is the table widget, the problem is it gets located at position x 0 y 0 of the table widget. I use setCellWidget method and it still doesn't populate the correct cell no matter what row and column I specify there. What should I do then?
I've found this example in PyQt but whenever I try to implement a ruby-esque version of it on Ruby it just doesn't work.
This code does what you were looking for: generate a n×m table, and insert a combobox at a given cell, here at row 4 / column 2.
require 'Qt4'
qt_app = Qt::Application.new(ARGV)
win = Qt::Dialog.new
win.show
table_widget = Qt::TableWidget.new(win)
layout = Qt::GridLayout.new(win) # not required
layout.addWidget(table_widget) # not required
rows = table_widget.rowCount = 7
columns = table_widget.columnCount = 4
(0..rows-1).each do |row|
(0..columns-1).each do |column|
text = "cell #{row}/#{column}"
table_widget.setItem(row,column, Qt::TableWidgetItem.new(text))
end
end
combo_box = Qt::ComboBox.new(table_widget)
combo_box.insertItems(0, ["one", "two", "three", "four", "five"])
table_widget.setCellWidget(4, 2, combo_box)
table_widget.show
qt_app.exec

Using CheckBoxes to manage selection in an NSTableView

I have the classic setup of an NSTableView with the columns bound to various keyPaths of the arrangedObjects of an NSArrayController, and the NSArrayController bound to an array of dictionaries.
With this setup, selecting one or multiple rows in the tableview works automatically. The table view and array controller work together and it's easy to query the NSArrayController to get the list of selected objects.
One of my table columns contains NSButtonCells, the checkbox kind. Is there a way to use Cocoa Bindings to bind the checkbox in each row to that row's selection state ? I know that I could add another value to the NSDictionary representing each row, but that would duplicate the selection information that is already available in NSArrayController.
If it is necessary to do that, would also appreciate a quick sketch of your implementation.
Thanks
So, the answer to this is not for the faint of heart. The reason is you are trying to get NSTableView to do something it doesn't naturally want to do.
Start out by using cocoa's native NSTableView multiple selection behavior:
- clicking on a row selects it and deselects other rows
- holding control and clicking on a column toggles the selection state of that row only
Now, add a column of checkboxes. For this row, the rules are different:
- clicking on a checkbox toggles the selection state of that row only
This would be easy if we could capture clicks to the checkboxes and process them ourselves. Now we can, but the problem is that after we process them, they still get forwarded on to the NSTableView, altering the selection in the usual way. [Note: there may be some way to avoid this forwarding - if you know of one, please let me know]
So here's how you can (finally) accomplished this:
- add a "selectedInView" field to each object in the underlying object array. Add an observer to the associated NSArrayController for the keyPath: "selectedObjects". When the selection changes, set the selectedInView field accordingly for each object. Something like this:
if([keyPath isEqualToString:#"selectedObjects"]) {
// For table view checkbox's: keep "selectedInView" of song dictionaries up to date
[_arrayController.arrangedObjects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
BOOL sel = [_arrayController.selectedObjects containsObject:obj];
if([[obj objectForKey:#"selectedInView"] boolValue] != sel)[obj setValue:[NSNumber numberWithBool:sel] forKey:#"selectedInView"];
}];
Now comes the tricky part: the only time the checkboxes malfunction are when there is already a selection present. Here are the types of cases:
Setup: Row's 1,2,3 are selected. Checkbox clicked on row 4.
Result: Checkbox on row four is selected. Row four is selected. Row's 1,2,3 are deselected (because that's what NSTableView does naturally)
To solve this, whenever a checkbox is clicked you need to create a temporary array to remember the current selection, plus or minus the checkbox that just got clicked:
- (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
if([tableColumn.identifier isEqualToString:#"CheckBox"]) {
NSMutableDictionary *song = [_arrayController.arrangedObjects objectAtIndex:row];
if(!_tempSelectedSongs && _arrayController.selectedObjects) _tempSelectedSongs = [[NSMutableArray arrayWithArray:_arrayController.selectedObjects] retain];
if(_tempSelectedSongs) {
if([_tempSelectedSongs containsObject:song]) {
[_tempSelectedSongs removeObject:song];
} else if(![_tempSelectedSongs containsObject:song]) {
[_tempSelectedSongs addObject:song];
}
}
}
}
Now after the tableview has done it's selection processing, we want to set the selection to what it should be. There is a promising looking function that allows you to modify the tableview selection BEFORE it actually does the selecting. You can modify it like so:
- (NSIndexSet *)tableView:(NSTableView *)tableView selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes {
NSMutableIndexSet *newSet = [NSMutableIndexSet indexSet];
if(_tempSelectedSongs) {
NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
[_tempSelectedSongs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSUInteger index = [_arrayController.arrangedObjects indexOfObject:obj];
if(index != NSNotFound) [indexSet addIndex:index];
}];
proposedSelectionIndexes = indexSet;
[_tempSelectedSongs release]; _tempSelectedSongs = nil; [_tempSelectedSongsTimer invalidate]; [_tempSelectedSongsTimer release]; _tempSelectedSongsTimer = nil;
}
[proposedSelectionIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
NSProgressIndicator *progress = ((BDDiscreteProgressCell *)[[_arrayController.arrangedObjects objectAtIndex:idx] objectForKey:#"BDCell"]).progress;
if(!progress)
[newSet addIndex:idx];
}];
return newSet;
}
This works great, however there is a problem with the order in which the NSTableView delegate functions are called. Obviously we need the first function - where we setup the temporary array - to be called BEFORE the second function - where we use the information.
For whatever reason, it turns out that when you DE-select a checkbox, this is how things work,
but when you SELECT a checkbox, the opposite occurs. So for this case, you can add some more code to your above keyPath observer:
if([keyPath isEqualToString:#"selectedObjects"]) {
if(_tempSelectedSongs) {
_arrayController.selectedObjects = _tempSelectedSongs;
[_tempSelectedSongs release]; _tempSelectedSongs = nil;
}
// For table view checkbox's: keep "selectedInView" of song dictionaries up to date
[_arrayController.arrangedObjects enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
BOOL sel = [_arrayController.selectedObjects containsObject:obj];
if([[obj objectForKey:#"selectedInView"] boolValue] != sel)[obj setValue:[NSNumber numberWithBool:sel] forKey:#"selectedInView"];
}];
}
Edit: turns out there is an additional case: if a single row is selected and it's checkbox is "unclicked," this does not automatically trigger a selectedObjects notification, so you must run a function on a timer to implement the new selection.

Resources