void MainWindow::edit()
{
//Check if item is selected, if not return
const int row = list->currentRow();
if( row == -1 )
return;
EditWindow w( this, currentCategory() );
switch( currentCategory() )
{
case cApp:
{
App old = appList.at( row );
w.setApp( old );
if( w.exec() == QDialog::Rejected )
return;
if( old == w.app() ) return;
else old = w.app();
if( dm->updateApp( old ) ){
appList.replace( row, old );
list->item(row)->setText( old.name() );
}
break;
}
case cFilm:
{
Film old = filmList.at( row );
w.setFilm( old );
if( w.exec() == QDialog::Rejected )
return;
if( old == w.film() ) return;
else old = w.film();
if( dm->updateFilm( old ) ){
filmList.replace( row, old );
list->item(row)->setText( old.name() );
}
break;
}
case cSong:
{
Song old = songList.at( row );
w.setSong( old );
if( w.exec() == QDialog::Rejected )
return;
if( old == w.song() ) return;
else old = w.song();
if( dm->updateSong(old) ){
songList.replace( row, old );
list->item(row)->setText( old.name() );
}
break;
}
}
displayItem(row);
}
This code checks which category we have at the moment. Then it edits an app, a movie or a song (depends on the category). Then when I change some informations it writes these changes to the database and the global QLists, change the name in the QListWidget and displays the current item's information in a few labels (it's the last function).
As you can see it's the same code except that the QLists are different. Movies and songs work perfectly. I can change every detail and it automatically updates the name in the list.
But when I change the name of an app and click ok it doesn't change the name in the list and doesn't change the apps information in the QList.
However, when I go through it with a debugger and click on every single step the list changes the name and the information.
So basically what I am trying to ask is why does this code above work when using the debugger going through each step but not when just running it?
I guess that what you call "simple running" is actually using your IDE in "build to run" mode and you are in fact comparing a debug build with an optimised release build. The debugger properly initialises all memory to zero which doesn't happen in the release build.
Regardless of what you are doing, this behaviour is indicative of illegal memory access.
From your code everytime you use at() you are at risk of going out of bounds and I guess that is what is happening. You should check all instances of at() and also list->item(row) are not going out of bounds.
Furthermore using list is at risk of being confused with std::list, therefore this variable should be renamed.
Related
I use C++ Builder 2009 and have implemented a Listview virtually.
Recently I learned of an issue that (so far) only happens for 3 people out of thousands. (Obviously there must be more instances, but they remain unreported so far).
What happens is that when the user hovers over the items in the ListView control, from bottom to top, the items in the list change.
Since the control is implemented virtually the software provides the information via an event and for 'a' reason the software gets the wrong index to work with when hovering from bottom to top.
See this little video to understand the behaviour better:
https://www.youtube.com/watch?v=jNZkaBH24PY
I have been searching for a reason, on and off, for some time, hampered by the fact that I cannot repeat this problem myself, so I needed to send special builds to 1 of the 3 willing to help. And I was finally able to pinpoint it to the use of Overlay icons !
I assign an icon to the items in the list by asking Windows what icon is relevant via SHGetFileInfo
The event:
void __fastcall TFinder::ListViewData(TObject *Sender, TListItem *Item)
{
DListView->OnData(Item, DirInListView->Object(Item->Index)) ;
}
Code called by the event:
HANDLE ObjectDisplayInListView::OnData (TListItem *ListItem, DataObject *Object)
{
ListItem->Data = (void*) Object ;
ListItem->Caption = String(Object->DisplayName().c_str()) ;
if (!SystemIconsSet)
{
ListItem->ImageIndex = Object->Icon() ;
ListItem->OverlayIndex = Object->IconOverlay() ;
}
else
{
int Icon = SystemIcon(Object) ;
ListItem->ImageIndex = (Icon & 0x00FFFFFF) ;
ListItem->OverlayIndex = (Icon >> 24) - 1 ;
}
ListItem->Cut = Object->IconGreyed() ;
ListItem->StateIndex = Object->IconState() ;
return (HANDLE) ListItem ;
}
// The SystemIcon() routine:
int ObjectDisplayInListView::SystemIcon (DataObject *Object)
{
// SHFILEINFO info ; The class declared one will do !
info.hIcon = NULL ; // Just making sure
DWORD Res = SHGetFileInfoW( Object->DisplayName().c_str(),
FILE_ATTRIBUTE_NORMAL,
&info,
sizeof(SHFILEINFO) ,
SHGFI_ICON |
SHGFI_USEFILEATTRIBUTES |
SHGFI_OVERLAYINDEX
) ;
DestroyIcon(info.hIcon) ;
return info.iIcon ;
}
The subclass code (which can be removed completely and the problem still exists !!)
void __fastcall TFinder::LVNewWindowProc(Messages::TMessage &Msg)
{
if( LVOldWindowProc ) LVOldWindowProc( Msg );
if (Msg.Msg == WM_NOTIFY) // Sort arrows
{
// Not relevant for this Q but added since it is in my code
switch(((LPNMHDR)Msg.LParam)->code)
{
case HDN_ENDTRACKA:
case HDN_ENDTRACKW:
case HDN_ITEMCHANGEDA:
case HDN_ITEMCHANGEDW:
{
if(((LPNMHDR)Msg.LParam)->hwndFrom == ListView_GetHeader(ListView->Handle))
{
if (ObjInListView && dynamic_cast<FileDirObject*>(ObjInListView) && ListView->Items->Count)
{
SetSortArrow(SortingTypeToDesignColumn(UISortingType), UISortingDirection) ; // Show the arrow based on what sorting was used
}
}
}
break;
}
}
else if (Msg.Msg == CN_NOTIFY && Platform > OS_PLATF_WINXP)
{
if (reinterpret_cast<LPNMHDR>(Msg.LParam)->code == LVN_GETDISPINFOW)
{
LV_ITEM &item = reinterpret_cast<LV_DISPINFO*>(Msg.LParam)->item ;
int OverlayIndex = -1 ;
TListItem *ListItem = ListView->Items->Item[item.iItem] ;
if (ListItem) OverlayIndex = ListItem->OverlayIndex ;
if (OverlayIndex >= 0)
{
item.mask |= LVIF_STATE ;
item.state |= INDEXTOOVERLAYMASK(OverlayIndex + 1) ;
item.stateMask |= LVIS_OVERLAYMASK ;
}
}
}
}
I implemented this based on an older question, asked here as well: Can't get Windows Overlay icons to work in TListView
To be more precise, this function has been working great for me for over 10 years, but about a year ago I added SHGFI_OVERLAYINDEX as well
The issue, as explained and as can be seen in the video, disappears entirely when I simply and only remove SHGFI_OVERLAYINDEX from the function call.
For whatever reason also asking for the overlay icon, causes the weird behaviour.
Even when I completely disable the CN_NOTIFY message subclassing that goes along with this functionality (see: Can't get Windows Overlay icons to work in TListView ) but call SHGetFileInfo() with SHGFI_OVERLAYINDEX, the problem happens !
Does anybody have an idea what this could be ?
A solution could be to not ask for the overlay icon on these problematic systems, but then I need to find a way to actually detect that the problem is going to happen (or is happening) somehow.
bool win::checkIfFScreen(sf::RenderWindow &window)
{
TiXmlDocument doc;
TiXmlElement * fullscreen;
if(!doc.LoadFile("videoSettings.xml"))
{
fullscreen = new TiXmlElement( "Window" );
fullscreen->SetAttribute("Fullscreen: ", 0);
doc.LinkEndChild( fullscreen );
fullscreen->Attribute("Fullscreen: ");
std::cout << typeid(*fullscreen->Attribute("Fullscreen: ")).name() << std::endl;
doc.SaveFile("videoSettings.xml");
return false;
}
if(*(fullscreen->Attribute("Fullscreen: ")) == '0')
return false;
return true;
}
Idea:
So, I wanna store information about persons preference if he wants for the game to be fullscreen or windowed. I've created this bool function that checks if there is "videoSettings.xml" file and returns information about users preference. If the file doesn't exists it will be create with Fullscreen set to 0 (which basically means that the game will be windowed and the user could change it later in the game's settings).
Part that doesn't work:
if(*(fullscreen->Attribute("Fullscreen: ")) == '0')
return false;
After adding this two lines I've got Segmentation fault (core dumped).
It seems that that value is stored as char.
EDIT:
This lines solved everything :) .
TiXmlHandle docHandle ( &doc );
TiXmlElement *child = docHandle.FirstChild( "Window" ).ToElement();
if(child)
if(*child->Attribute("fullscreen") == '1')
return true;
else if(*child->Attribute("fullscreen") == '0')
return false;
Thank you #frasnian .
Your code has this:
TiXmlElement * fullscreen; // not initialized to anything here
if(!doc.LoadFile("videoSettings.xml")) // LoadFile returns true on success
{
fullscreen = new TiXmlElement( "Window" ); // okay
...
return false;
}
// question: if doc.LoadFile() succeeds, what is this going to do-
if(*(fullscreen->Attribute("Fullscreen: ")) == '0')
return false;
You are using fullscreen before it is initialized with anything.
On edit
In response to question in comment:
If loading the document succeeds, you need to get the root element with something like:
TiXmlElement* root = doc.FirstChildElement("Whatever"); // root element name
if (root){
TiXmlElement* el = root->FirstChildElement("Window"); // etc, etc,
When you have walked the document hierarchy to wherever your "Window" element is, use TiXmlElement::Attribute() or TiXmlElement::QueryAttribute() to get the value of the attribute (if it exists).
A better approach than walking the hierarchy with FirstChild/NextSibling, etc. (inherited by TiXmlElement from TiXmlNode) is probably to use handles. See the docs for TinyXML related to TiXmlHandle - the main docs page has an example that is pretty straightforward.
As a side note, the colon after the attribute name in your posted code should be removed (i.e. "fullscreen", not "Fullscreen:").
Also, this line:
fullscreen->Attribute("Fullscreen: ");
right after you call LinkEndChild() does not do anything.
In ActionScript, I can just check the .stage property of a DisplayObject, and if it's null, then the DisplayObject isn't on the display list. Is there a cocos2d equivalent?
I'm controlling my own touch system for buttons etc, and I want a quick way to ignore buttons that are registered but not actually on the screen. I'm currently checking against visible and parent, but that doesn't go all the way up the chain, so if I have a popup in memory that's not visible/attached to anything, and a button as a child inside that popup, the button check will pass (as it's visible and has a parent).
Aside from looping all the up until the scene, is there an easy way to check if a CCNode/CCSprite is on the display list?
Edit
Working on #HariKrishna's answer, this was the code I came up with as the cocos2d-x implementation wasn't exactly what I was looking for (e.g. if the parent of the node was nil, then it would return YES as it would never enter the check):
- (BOOL) hasVisibleParents
{
CCNode * p = self.parent;
while( true )
{
if( p == nil || !p.visible )
return NO;
if( [p isKindOfClass:[CCScene class]] )
return YES;
p = p.parent;
}
return YES;
}
You can use CCNode::isVisible() and CCControl::hasVisibleParents() which will internally go up to all the node hierarchy...
Thats the closest you can get for the same.
Example:
bool presentInDisplayList() {
if(isVisible() && hasVisibleParents())
return true;
else
return false;
}
Where hasVisibleParents() is, (Copied from Cocos2d-X Library)
bool CCControl::hasVisibleParents()
{
CCNode* pParent = this->getParent();
for( CCNode *c = pParent; c != NULL; c = c->getParent() )
{
if( !c->isVisible() )
{
return false;
}
}
return true;
}
This can be easily translated to Objective-C
So for about a week i have been looking for solution of my problem. I have prepared my own model (after QAbstractTableModel) and it is displayed at default qTableView. I added to main menu an option, it is editiog an item:
void Window::EditPerson()
{
console->alert( "Choosing person" );
//console->alert( /*(QString)"Chosen person " +*/ QString::number( mainWidget->selectionModel()->selectedIndexes().size() ) );
if( mainWidget->selectionModel()->selectedRows().size() <1 )
return;
//console->alert( /*(QString)"Chosen person " +*/ QString::number( mainWidget->selectionModel()->selectedIndexes().size() ) );
//Person x = family->GetPerson( mainWidget->selectionModel()->selectedIndexes().value( 0 ).row() );
//EditPersonDialog( x );
}
Rapidly after calling this function (which is also the slot) in case there is selected any item i get RTE.
Thanks in advance for any help.
You should null-check the return value of selectedRows(). Although the documentation doesn't say, I think it might be NULL if there is no selection (which I assume you want to check in the condition).
I have a menu button inside a CMFCToolbar and I would like to replace the bitmap of the button each time a different entry is selected in the menu as each entry has its own icon.
I succeed in changing the icon using CMFCToolBarMenuButton::SetImage but it changes the icon in the menu entry too. Too bad.
alt text http://www.freeimagehosting.net/uploads/137269b0f2.jpg alt text http://www.freeimagehosting.net/uploads/879d03843a.jpg
Here is a sample of code:
if ( (pToolbar != NULL) && (idBase != 0) )
{
int ixButtonToReplace = pToolbar->CommandToIndex(idBase);
CMFCToolBarMenuButton* pBtnToReplace = dynamic_cast<CMFCToolBarMenuButton*>
(pToolbar->GetButton(ixButtonToReplace));
if ( pBtnToReplace )
{
const CObList& listCommands = pBtnToReplace->GetCommands();
POSITION pos = listCommands.GetHeadPosition();
while ( pos != NULL )
{
CMFCToolBarMenuButton* pItem = (CMFCToolBarMenuButton*) listCommands.GetNext(pos);
if ( pItem && (pItem->m_nID == idButtonToReplaceWith) )
{
pBtnToReplace->SetImage(pItem->GetImage());
}
}
}
}
Any ideas? Thank you.
It works out-of-box. The only you need is to call CMFCToolBar::AddToolBarForImageCollection so MFC could know which images to use.
Not sure what you mean by the menu button is changed too?
If another button is changed with the single setImage call to the obvious indication is they share a resource ID of some sort, the only solution would be to ensure they have different ID's (which would require making sure both resources are handled separately).
But it's a long time since I messed in MFC resource files to confirm this.