Extjs4 tree panel borrow from grid panel - grid

I was trying to implement lockable feature on tree.Panel so i borrowed from grid.Panel
Ext.tree.Panel(Ext.grid.Panel, ['bothCfgCopy','normalCfgCopy','lockedCfgCopy']);
but now my grid columns are objects i.e a column.$className on a tree.Panel would return an object because they have been transformed.
How do i hide columns now as all functionality such as hide(), setVisible() have been lost ?
Thanks in advance

It might not still be relevant, but here's an example of a buffering locking grid.
You can set buffering to false and use as is, or you can use it as a guideline for you current implementation.

Related

Autoscrolleable TableView

I think this is an easy one, but I can't solve it by myself.
I'm using a TableView from QML, and from Qt with a timer I'm sending info to the TableView to generate new rows.
I want the TableView autoscroll itself and always showme the last row I add
Use
ListView.positionViewAtEnd();
to scroll to the end of list or use
ListView.positionViewAtIndex(int index, PositionMode mode)
to scroll to specified index.
Pay attention, you must call this functions only after the list was loaded (generally in Component.onCompleted)
I find an answer
TableView.positionViewAtRow( TableView.rowCount -1, ListView.End)
I used folibis/Benjamin answer but I have to do it with a TableView, I found this answer to my problem, hope it helps some one else

Updating sort-order indicator in QTableView/QHeaderView when model is sorted

I want to know how to ensure the sort indicator in the horizontal header of a QTableView is updated when a programmatic sort is performed on the model.
Here's the problem:
QStandardItemModel model(3,1);
QTableView view;
view.setModel( &model );
// Populate the model ensuring it is not in a sorted order
for( int row = 0; row < model.rowCount(); ++row )
{
model.setItem( row , 0 ,
new QStandardItem(QString::number((row+1)%model.rowCount())));
}
view.setSortingEnabled( true );
// At this point everything is consistent since enabling the sorting
// triggers a sort that matches the indicator in the horizontalHeader (see A)
model.sort( 0 , Qt::AscendingOrder );
// However at this point the sort order has been reversed but the
// header's sort indicator remains unchanged (see B)
A: B:
As you can see the sort indicator remains the same and therefore is inconsistent with the actual sort order.
In my application I have two views that interact with the same model and sorting can be triggered from either of them. I don't see anything in QAbstractItemModel that signals when a sort has been performed. It seems like QHeaderView/TableView assume that they are the only thing that can trigger a sort.
Does Qt provide facilities for coping with this that I'm missing? If not, what's the best way of keeping the sort indicator up-to-date without breaking the encapsulation of the multiple views on the model too much?
One of the ItemDataRole enumerators available since Qt 4.8 is InitialSortOrderRole.
http://qt-project.org/doc/qt-4.8/qt.html#ItemDataRole-enum
It should therefore be possible to transmit sort order information through the QAbstractItemModel::headerData method.
I've tried this however and found that QTableView and QHeaderView do not seem to update in response to changes in this headerData role. A customised header view would appear to be necessary...
It might be worth it because passing this information via the model allows any number of views to synchronise without any external agent having to track all the views in existence so that it can distribute notifications. It would also work seamlessly through model proxy stacks such as those built with QSortFilterModelProxy.
The solution I've come up with to avoid breaking encapsulation too much is
to have a signal on each view (on QTableView the sortIndicatorChanged signal suffices and on my custom view I have added a similar signal).
the manager of views connects to these signals
when any view emits such a signal the manager of views calls a slot on all the other views so that they can synchronise their sort indicators
I still feel like I might be missing something - surely this is a common problem? It seems to me that QAbstractItemModel should have a way of transmitting sort-order information to views...

How do I implement a horizontally populated DataGrid (with the headers on the left instead of at the top)?

I am trying to find an easy and robust way to override the default layout of DataGrid and populate its values in a left-right fashion. To illustrate:
My data model is an array of: {a: xxx1..n, b: yyy1..n, c: zzz1..n}
The default DataGrid component will lay this out as:
a b c
xxx1 yyy1 zzz1
xxx2 yyy2 zzz2
xxxn yyyn zzzn
etc.
With "a", "b", and "c" as the headers, and x, y, z being their values for each object in the dataProvider.
Now I want to lay this out horizontally like so:
a xxx1 xxx2 xxxn
b yyy1 yyy2 yyyn
c zzz1 zzz2 zzzn
I've searched around for an answer but haven't hit on anything. Perhaps I'm just using the wrong keyword searches...
Regardless, if anyone knows a solution to this, be it as mundane as a property setting I've somehow missed, or a 3rd party component, etc. I would be very grateful!
ps: Eventually, this must be entirely tab-enabled and cell-editable. If you have an esoteric solution involving a multi-field itemRenderer, please keep this in mind. I mention this because I have attempted such a solution and have failed to penetrate DataGrid's Unfailing Field of Tab Vitiation (ie DataGrid seems to override tab functionality inside its itemRenderer, forcibly setting focus to the next renderer/editor).
I think this is not possible.
Normally, you can manage this with skin classes (for a sparkPanel). There are a nice tutorial from adobe (flex in a week).
In flex hero (the prerelease of flex 5), the datagrid is also implement in spark. I think, then this will be possible.
BR
Frank

In Qt, create a table with an blank editable row

This is a Qt-specific question.
It's convenient to be able to add new data to a table by typing content into a blank row at the bottom of a table. When the data is committed, a new blank row is added to the table.
Has anyone found a way of implementing this in a generic way, that fits into Qt's model-view programming architecture? My closest attempt involves creating a proxy model, such that the rowCount() returned from the model is always one greater than the source model.
QAbstractTableModel* sourceModel ; // Data is stored here
QBlankRowModel* model ; // Proxy model that adds one to rowCount()
QTableView* view ; // View
view->setModel( model ) ;
model->setSourceModel( sourceModel ) ;
Any suggestions are welcome. Thanks.
From a design-perspective, this should be part of the view, not the model. Therefore, I suggest implementing a view with the functionality and leave the model unchanged. KOffice Kexi does just this with kexitableview (screenshot, documentation). Maybe you want to use some of their code.
BTW, you might still be able to use your hack and combine it with my suggestion by putting it inside a new table view implementation YourTableView:
QBlankRowModel re-implements the
QAbstractTableModel
interface. It returns sourceModel.rowCount()+1 as the QBlankRowModel::rowCount().
It returns a QVariant() if the n+1th row is requested in QBlankRowModel::data().
All the rest within QBlankRowModel is forwarded to the sourceModel (with editing
the n+1th row in QBlankRowModel buffered and replaced with inserting into the
sourceModel when finished).
The new YourTableView inherits from
QTableView and wraps the sourceModel within
YourTableView::setModel(), calling
QTableView::setModel(QBlankRowModel(sourceModel)).
Thereby, your hack is localized at one point.
Your solutions seems a little hackish. Your problem is not only additions, it's also editions. What happens when your user edits a row, the typed data goes directly to your "data layer" even before the user commits his edition?
A better solution would be to restrict the role of your sourceModel. Rather than being a "direct" representation of your data, it should be a "buffered" representation of it. When the sourceModel is created, you make a copy of your data in some kind of Row() instances. The sourceModel, having its own copy of the data can then freely play around, perform editions and additions, and only commit the data to your model layer when the user commits his edits.
If you want a PyQt example of such a table, you can look at the source of a project of mine:
http://hg.hardcoded.net/moneyguru/
You might have to dig around to actually find the "buffering" logic because it's not in the PyQt code itself, but rather the "cross-platform" part of the code:
http://hg.hardcoded.net/moneyguru/src/tip/core/gui/table.py
This logic is then used in my QAbstractItemModel subclass:
http://hg.hardcoded.net/moneyguru/src/tip/qt/controller/table.py
Sounds like a reasonable solution, as it should work for any model that you might want as the actual table model, ie. SqlTableModel or just a plain one. As long as you add the row when the user is done editing and take care not to add the row when the user did not add any data.

'Pre-measuring' Flex Components

I'm implementing a custom Flex component that provides a scrollable viewpoint onto a (possibly very large) data grid. I'm using the ItemRenderer pattern, such that I only have UIComponents for the elements visible on the screen at a given time. In other words, something similar to the standard DataGrid control.
One requirement I have is to dynamically size the grid cells to fit the provided data, such that the column widths and row heights are known up front. (The column widths and row heights can't fluctuate as the user scrolls and new cells come into view.)
This requirement implies a 'pre-measure' phase of the entire grid to be performed when the component's dataSource or itemRenderer is changed. I'd like to use the standard Flex component measuring operations to perform this pre-measurement phase.
My current strategy for this pre-measure phase is to:
Obtain an itemRenderer instance
Initialize the itemRenderer
For each cell in the data source:
Set the itemRenderer's 'data' object to that cell's data
'commitProperties()' on the component
'measure()' the component
Update column width/row height appropriately based on measurement results
I'd rather not attach the itemRenderer to the application's display list, but that means it won't be initialized by the framework. Also, I need the renderer's initialization and commitProperties/measurement phases to occur synchronously. I'm scared of how much of the Flex component lifecycle management framework I'll have to replicate to accomplish this.
So I call on those more experienced than I for words of wisdom:
Any thoughts on the feasibility of this strategy?
Any suggestions on how I could elegantly make use of the framework to perform this measurement for me?
Any better strategies to determine cell size?
I studied the framework code a bit, and if initial results are an indication, this isn't as painful as I feared. The guts of it:
var renderer:IListItemRenderer = getRenderer();
renderer.initialize();
for each (var cell:Object in cells) {
renderer.data = cell;
renderer.validateProperties();
renderer.validateSize(true);
// Access renderer's size properties here
}
Passing the 'recursive = true' flag to validateSize is the key that I was missing previously. Unfortunately there's no equivalent flag for validateProperties, so I'll probably have to implement that myself to make it reliable for arbitrary ItemRenderers.
I've never applied itemRenderers this way, so, not sure how much this would come into play with you're approach, but are you setting
super.data = data
at the top of your renderer's data setter? i.e:
override public function set data(value:Object):void
{
super.data = value;
...
}
If not, you might try adding that and see if it removes the need for a recursive flag in validateProperties().

Resources