Perl Gtk3::ScrolledWindow that contains more than one Gtk3::TreeView child. How do you disable child from scrolling to the top when selecting a row? - perl

I am writing a program in Perl using Gtk3. I have a left sidebar (not using any sidebar widgets) that contains multiple tree views.
I it setup like this:
my $sidebarscrollarea = Gtk3::ScrolledWindow->new( undef, undef );
my $sidebarlabelaccounts = Gtk3::Label->new("Accounts");
$sidebarlabelaccounts->set_halign('GTK_ALIGN_START');
my $sidebarlabelincome = Gtk3::Label->new("Income Envelopes");
$sidebarlabelincome->set_halign('GTK_ALIGN_START');
my $sidebarlabelexpense = Gtk3::Label->new("Expense Envelopes");
$sidebarlabelexpense->set_halign('GTK_ALIGN_START');
# *_create_model() builds the models
my $account_tstore = account_create_model();
my $income_tstore = envelope_create_model();
my $expense_tstore = envelope_create_model();
# populate the models with another subroutine
populate_models();
my $accountslist = Gtk3::TreeView->new();
$accountslist->set_model($account_tstore);
my $incomelist = Gtk3::TreeView->new();
$incomelist->set_model($income_tstore);
my $expenselist = Gtk3::TreeView->new();
$expenselist->set_model($expense_lstore);
# Add columns to model and view via view ( Gtk3::TreeView )
account_add_columns($accountslist);
envelope_add_columns($incomelist);
envelope_add_columns($expenselist);
my $sidebarbox = Gtk3::Box->new('vertical',1);
$sidebarbox->set_border_width(5);
$sidebarbox->pack_start($sidebarlabelaccounts,0,0,5);
$sidebarbox->pack_start($accountslist,0,6,5);
$sidebarbox->pack_start($sidebarlabelincome,0,0,5);
$sidebarbox->pack_start($incomelist,0,6,0);
$sidebarbox->pack_start($sidebarlabelexpense,0,0,5);
$sidebarbox->pack_start($expenselist,0,6,0);
$sidebarscrollarea->add($sidebarbox);
The envelopeslist is very long. When I click a row from that list that is toward the bottom of the window, it scrolls so that the envelopes list at the top of the window. I do not want it to move anywhere regardless of where I click a row. Thanks for your help. I am new to all of this.

Simply adding:
$expenselist->set_can_focus(FALSE);
solves my problem.

Related

Get tab status using pyforms

I'm working with pyforms to create a tab widget and I want to get and set the current active tab. Consider this example:
self.formset = [{
'Person A': ['_firstname', '_lastname'],
'Person B': ['_firstname', '_lastname'] }]
so we get 2 tabs Person A and Person B. If I switch between them I would like to be informed with something similar to PyQt function currentIndex(). So far I havn't been able to find a method in the pyforms documentation, is there a way to accomplish this just using pyforms?
The main issue in getting or setting the current index of your tab widget is to get access to the QTabWidget created by pyforms when the layout is generated. Once you have access to it, you simply call the setCurrentIndex(int)/currentIndex() of the widget.
A (dirty) quick fix to this is to modify the BaseWidget.py located in the pyforms module files which can be <VIRTUALENV_DIR>/lib/python3.6/site-packages/pyforms/gui when using virtualenv.
def generate_tabs(self, formsetdict):
"""
Generate QTabWidget for the module form
#param formset: Tab form configuration
#type formset: dict
"""
tabs = QTabWidget(self)
for key, item in sorted(formsetdict.items()):
ctrl = self.generate_panel(item)
tabs.addTab(ctrl, key[key.find(':') + 1:])
self.tabs = tabs
return tabs
Note the additional :
self.tabs = tabs
Then in the code of your widget/app (subclass of BasicWidget) :
>>> _t = self.tabs
>>> _t.setCurrentIndex(3) # activate the 4th tab
>>> print(_t.currentIndex())
3

Enterprise Architect: Hide only "top" labels of connectors programmatically

I want to hide the "top" part of all connector labels of a diagram. For this, I tried to set up a script, but it currently hides ALL labels (also the "bottom" labels which I want to preserve):
// Get a reference to the current diagram
var currentDiagram as EA.Diagram;
currentDiagram = Repository.GetCurrentDiagram();
if (currentDiagram != null)
{
for (var i = 0; i < currentDiagram.DiagramLinks.Count; i++)
{
var currentDiagramLink as EA.DiagramLink;
currentDiagramLink = currentDiagram.DiagramLinks.GetAt(i);
currentDiagramLink.Geometry = currentDiagramLink.Geometry
.replace(/HDN=0/g, "HDN=1")
.replace(/LLT=;/, "LLT=HDN=1;")
.replace(/LRT=;/, "LRT=HDN=1;");
if (!currentDiagramLink.Update())
{
Session.Output(currentDiagramLink.GetLastError());
}
}
}
When I hide only the top labels manually (context menu of a connector/Visibility/Set Label Visibility), the Geometry property of the DiagramLinks remains unchanged, so I guess the detailed label visibility information must be contained somewhere else in the model.
Does anyone know how to change my script?
Thanks in advance!
EDIT:
The dialog for editing the detailed label visibility looks as follows:
My goal is unchecking the "top label" checkboxes programmatically.
In the Geometry attribute you will find a partial string like
LLT=CX=36:CY=13:OX=0:OY=0:HDN=0:BLD=0:ITA=0:UND=0:CLR=-1:ALN=1:DIR=0:ROT=0;
So in between LLT and the next semi-colon you need to locate the HDN=0 and replace that with HDN=1. A simple global change like above wont work. You need a wild card like in the regex LLT=([^;]+); to work correctly.

adding/changing 'text' to an item in a group

I'm designing a UI with Enthought's TraitsUI, and I can't figure out how to get done what I want...
Here's what I want:
I have Items() in the view that I want to display as either English or SI units. I can change the value in the 'edit' box based on a SI/English button, but I can't figure out how to change the text of the label. For example, if I have an item 'Length, ft [ 3.28]' and convert it to SI, I'd like it to show 'Length, m [ 1.00]'. I can handle the 3.28->1.00 conversion, but can't figure out how to change the 'ft' to 'm'.
Any suggestions?
One thing I've tried is to define a string which holds the units name (like 'm' or 'ft')...then, in the item, I set the label like this:
label = 'Top, '+lengthUnits
This works fine when the view is first built, but it doesn't update the label when I change the units control. Is there some way to force the view to update with all the new values?
Here's a small py program that shows what I'm trying to do (feel free to critique my style :)). I'll also try and add in a couple of images that shows what happens:
# NOTE: This version of the code has been modified so that it works as I want it to :)
# Example trying to change text on a View...
from traits.api \
import HasTraits, Enum, CFloat, String
from traitsui.api \
import View, Group, HGroup, Item, spring
class TestDialog ( HasTraits ):
length = CFloat(1.0)
choose_units = Enum('English', 'SI')
current_units = 'English'
unit_name = String('ft')
ft_to_m = CFloat(3.28)
view = View(
Group(
HGroup(
spring,
Item(name = "length", label = 'Test length'),
Item(name = 'unit_name', style = 'readonly', show_label = False),
spring
),
HGroup(
spring,
Item(name = "choose_units"),
spring
)
),
title = 'Test Changing View Test'
)
def _choose_units_changed(self):
if self.current_units != self.choose_units:
if self.choose_units == 'SI':
self.length /= self.ft_to_m
self.unit_name = 'm'
else:
self.length *= self.ft_to_m
self.unit_name = 'ft'
self.current_units = self.choose_units
# Run the program (if invoked from the command line):
if __name__ == '__main__':
# Create the dialog:
TestIt = TestDialog()
# put the actual dialog up...
TestIt.configure_traits()
Use a notification as described here: http://code.enthought.com/projects/traits/docs/html/traits_user_manual/notification.html
Update in response to updated question:
Right, labels are not dynamically updated. Instead, make a text field that looks like a label, e.g. with:
label_text = String('Test length, English:')
Then display it in your View with something like:
Item("label_text", style='readonly', show_label=False),
You'll probably also want to use an HGroup nested inside your (V)Group, to position it to the left of your "length" display.
Then modify label_text inside your listener.

TYPO3: Trying to add link to images

On our site, other admins add images via the "Resources" tab of the main page. These images are displayed as Banners in a Slider on the main page. However, now they want the ability to add links to specific images.
My first thought on this (after receiving some help on making a loop for images to be added to the page) was to perhaps let them be able to add the link to either the "Title" or "Caption" spot I saw there. And later, on the slider "create" function, pull the said data from the image and make <a> wrap around the image before the slider finished building. I've already tested the slider plugin with this functionality, and that would work fine, however, I can't seem to pull anything from the "Title" or "Caption" and add it to the image in any way.
My other thought would be, is there a way to extend the back end to give them an actualy spot to paste links on images so that I may pull that and wrap the image via the typoscript, or can i pull from caption and wrap image in <a> "if" the link is available.
In other words, does typoscript have a type of "if" statement? What I ahve so far, thanks to maholtz is as follows:
#BANNER IMAGES LOOP BEGIN
page.10.marks.topimage = TEXT
page.10.marks.topimage {
# retrieve data
data = levelmedia: -1, "slide"
override.field = media
# we have some filenames in a list, let us split the list
# and create images one by one
# if there are five images selected, the CARRAY "1" will be executed
# five times where current is loaded with only one filename
split {
# the images are separated via ","
token = ,
# you can do funny stuff with options split, f.e. if you want to give first
# and last image a different class... but thats another topic;)
# we just say, render every splitted object via CARRAY "1"
cObjNum = 1
1 {
# just render the single image,
# now there should be one filename in current only
10 = IMAGE
10 {
file.import.wrap = fileadmin/user_upload/|
file.import.current = 1
border = 0
file.height = 670
file.width = 1800
altText = Banner
titleText = Banner
# attempt to add link to image if available
caption.1.typolink.parameter.field = image_link
caption.1.typolink.parameter.listNum.stdWrap.data = register:IMAGE_NUM_CURRENT
}
}
}
wrap = <div id="slides">|</div>
}
#BANNER IMAGES LOOP END
I was thinking perhaps I could do something like:
10 {
file.import.wrap = fileadmin/user_upload/|
file.import.current = 1
border = 0
file.height = 670
file.width = 1800
altText = Banner
titleText = Banner
# attempt to add link to image if available
caption.1.typolink.parameter.field = ???
caption.1.typolink.parameter.listNum.stdWrap.data = register:IMAGE_NUM_CURRENT
}
But as you can see, I'm stumped on how that might even work right. Can anyone help point me the right way.
As before mentioned, perhaps I could do ONE of two things:
Pull link from "Title" or "Caption" and add it to the IMAGE Date on output so that I can use that client side to wrap the image in appropriate a tag, |OR|
Pull link from there and use typoscript to wrap the image in a tags
When accessing the ressources via levelmedia = slide you're not directly accessing the FAL table. Therefore you have to load it again to access the fields you want. We solved exactly the problem you have with the following code. Insert it inside your 1 after 10 = IMAGE.
typolink{
parameter{
cObject = RECORDS
cObject{
source.current = 1
tables = sys_file_reference
conf.sys_file_reference = TEXT
conf.sys_file_reference.field = #title or description
}
}
}

Can a dojo.dnd.Source object contains another dojo.dnd.Source object as one of the child nodes?

I have looked at the this link for a tutorial on dojo drag and drop feature. But one thing I have noticed is that in all cases of the examples, the items to be dragged around are always a simple item, just a string object...
I need to create something like an item group where you can drag an item into the item group to append into the group and to drag the item group around as a whole.
Hence my question, is it possible to drag and drop a dojo.dnd.Source item into another dojo.dnd.Source item?
Short answer: no. Many people tried to patch it, but found more and more non-working edge cases, so those patches never made the Dojo proper.
If you truly need to show and manipulate a hierarchical data, consider a Tree Dijit.
The problem is that when you start dragging and you drag over a Source of a child container, everything gets messed up. (Not exactly sure how). What you can do, is hide those child sources so that their overSource events never trigger:
1) Overrode the checkAcceptance function in Source.js. Just added the following for the if(!flag) return false;:
if(!flag){
/**
* Main Source
* - Group 1
* -- Child 1
* -- Child 2
* - Group 2
*/
var node = dojo.byId(this.node);
// If the node being moved is the source, skip, but don't hide from view.
if('#'+dojo.attr(source.node, 'id') != '#'+dojo.attr(node, 'id')){
// If the node being moved is an immediate child of the container, you can move it.
if(dojo.query('#'+dojo.attr(source.node, 'id') + '>#'+dojo.attr(node, 'id')).length) {
return true;
}
// If this source is not a parent of the element, hide it.
if(dojo.query('#'+dojo.attr(node, 'id') + ' #'+dojo.attr(source.node, 'id')).length == 0)
dojo.addClass(node, 'hiddenSource');
}
return false;
}
2) You need to also add the following as the first line under if(this.isDragging) in onMouseMove (important)
var node = dojo.byId(this.node);
// If this is immeditae child, drop it.
if(dojo.query('#'+dojo.attr(m.source.node, 'id') + '>#'+dojo.attr(node, 'id')).length){
m.canDrop(true);
return;
}
3) Extended onDndDrop to remove the added class to re display the hidden elements.
onDndDrop: function(source, nodes, copy, target)
{
this.inherited(arguments);
dojo.forEach(dojo.query('.hiddenSource'),
function(el){dojo.removeClass(el, 'hiddenSource');}
);
}
4) Extend onDndCancel to do the above
onDndCanel: function()
{
this.inherited(arguments);
dojo.forEach(dojo.query('.hiddenSource'),
function(el){dojo.removeClass(el, 'hiddenSource');}
);
}
This isn't the best solution since it hides the elements that can't be used with the current element that you are positioning, but it worked for me.