Qt Designer crashes with custom plugin - plugins

Created custom designer plugin similar to Container Extension Example. After some modifications with QDesignerCustomWidgetInterface, QDesignerContainerExtension and QExtensionFactory classes and adding following methods to my container:
Q_OBJECT
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex)
Q_PROPERTY(QString pageTitle READ pageTitle WRITE setPageTitle STORED false)
public:
WidgetBox(QWidget *parent = 0);
int count() const { return mTreeWidget->topLevelItemCount(); }
QWidget* widget(int index) const;
QString pageTitle() const;
public slots:
void setCurrentIndex(int index);
void addPage(QWidget *widget);
void insertPage(int index, QWidget *widget);
void removePage(int index);
int currentIndex() const { return mTreeWidget->currentIndex().row(); }
void setPageTitle(QString const &newTitle);
protected:
QTreeWidgetItem * addCategory(QString pageName);
QTreeWidgetItem * insertCategory(int index, QString pageName);
PageButton *categoryButton(int index) const;
void createContainerWidget(QTreeWidgetItem* page, QWidget *widget);
void createCategoryButton(QTreeWidgetItem* page, QString pageName);
signals:
void currentIndexChanged(int index);
void pageTitleChanged(const QString &title);
Qt designer started to crash on start with my plugin. Any way do debug plugin (extension) and found the cause? Plugin build in release mode with same Qt and VS C++ versions as Qt Designer and Creator - Based on Qt 5.5.1 (MSVC 2013, 32 bit).
P.S. So method is following: commented out extension and factory classes - still crashes, sequentaly commented/uncommented methods in my widget class: problem appears in
Q_PROPERTY(QString pageTitle READ pageTitle WRITE setPageTitle STORED false)
and methods pageTitle and setPageTitle for current page when no pages available. Need think what to set/output here when no pages were added. Or add at least 1 page by default.
Now Qt Designer crashes on adding widget to a form. Will continue searching the cause.

Added index check to widget() method, works fine for now. So need to check all methods that Qt Designer can call for potential crash (for example, with no pages in this case).

Related

How to retain the state of a treeviewer in Java RCP application?

I have a simple RCP application having couple of wizards out of which one is having a tree viewer. I want to retain the state of the selected item in the tree viewer next time I open that particular view. As of now I have implemented using static variables and its working fine.I want to know how it can be done in a better way?
//Sample Code
private static RepositoryLocationItem lastRepoItemSelected;
Composite parent=new Composite(SWT.NONE)
treeViewer = new TreeViewer(parent);
treeViewer.setContentProvider(new MovingBoxContentProvider());
treeViewer.setLabelProvider(new MovingBoxLabelProvider());
treeViewer.setInput(getInitalInput());
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
/* Setting the value of lastRepoItemSelected */
});
if(lastRepoItemSelected !=null)
{
treeViewer.setSelection(new StructuredSelection(lastRepoItemSelected),true);
}
Assuming this is a 3.x style RCP (your view extends ViewPart) you can use the saveState method to save your view state:
#Override
public void saveState(final IMemento memento)
{
// TODO set values in the 'memento'
}
You can then use the init method to restore values from the memento when the view is shown again:
#Override
public void init(final IViewSite site, final IMemento memento)
throws PartInitException
{
super.init(site, memento);
// TODO restore from 'memento'
}
Note: Mementos are persisted across restarts of your RCP so you need to store values in them which are valid in a new instance of the RCP.
Also look at the Eclipse wiki entry for more information.
For a WizardPage you can use the IDialogSettings. You must set this up in your Wizard using something like:
IDialogSettings pluginSettings = Activator.getDefault().getDialogSettings();
IDialogSettings wizardSettings = pluginSettings.getSection("id of your wizard");
if (wizardSettings == null) {
wizardSettings= new DialogSettings("id of your wizard");
pluginSettings.addSection(wizardSettings);
}
setDialogSettings(wizardSettings);
where Activator is your plugin activator class and "name of your wizard" is a id for your wizard (which can be anything as long as it is unique in your plugin).
In your wizard page you can then get the settings with:
IDialogSettings settings = getDialogSettings();
IDialogSettings has lots of methods for saving and restore various sorts of values, such as:
settings.put("key", "string value");
String value = settings.get("key");

Eclipse display browser in view

I am trying to create a plug-in, which will show local .html file inside internal browser. Currently i am extending class ViewPart, and writing code into its createPartControl method. Most of people are using this snippet
IWebBrowser browser = PlatformUI.getWorkbench().getBrowserSupport().createBrowser("SOMELABEL");
browser.openURL(url);
Problem is that this snippet opens another view where internal browser is opened, but in my case it needs to be in this view...
I also tried other forms of createBrowser method, e.g.
createBrowser(int style, String browserId, String name, String tooltip);
where i tried to configure flags, but all of these options just open another view or editor. Is there a way do draw HTML inside my view?
I have found the solution. Yes i have tried Browser control before, but i did not created Browser properly (wrong arguments). If anybody else tries to implement ViewPart displaying html pages via SWT, here is the code snippet.
public class CustomView extends ViewPart {
private static final String URL = "file:///d:/playground/d3/project.html";
#Override
public void createPartControl(Composite parent) {
final Browser browser = new Browser(parent, SWT.NONE);
browser.setUrl(URL);
}
#Override
public void setFocus() {
}
}

wicket download link clear feedback panel

I have couple of drop downdowns and a download link button. Based on the user selection, i get the file to be downloaded. if the user did not make a selection I show an error on the feedback panel. if the user then makes a selection and clicks on download link it works fine, but the previous feedback message is still visible. How do I clear it.
onclick of the download link, i tried the following, but no use
FeedbackMessages me = Session.get().getFeedbackMessages();
me.clear();
Probably it is
Session.get().cleanupFeedbackMessages()
even it has been changed in Wicket 6.x
I've found this post and I think it is time to share the way for Wicket 6.x and for Wicket 7.x, because Session.get().cleanupFeedbackMessages() was deprecated already.
To do it for Wicket 6.x you have to implement additional filter for the feedback panel. Where to do it, it is your decision to decide.
Create a new FeedbackPanel implementation by extending from the existing FeedBackPanel class
private class MessagesFeedbackPanel extends FeedbackPanel{
private MessageFilter filter = new MessageFilter();
public MessagesFeedbackPanel(String id){
super(id);
setFilter(filter);
}
#Override
protected void onBeforeRender(){
super.onBeforeRender();
// clear old messages
filter.clearMessages();
}
}
Provide a new Filter implementation, by implementing the existing IFeedbackMessageFilter interface
public class MessageFilter implements IFeedbackMessageFilter{
List<FeedbackMessage> messages = new ArrayList<FeedbackMessage>();
public void clearMessages(){
messages.clear();
}
#Override
public boolean accept(FeedbackMessage currentMessage){
for(FeedbackMessage message: messages){
if(message.getMessage().toString().equals(currentMessage.getMessage().toString()))
return false;
}
messages.add(currentMessage);
return true;
}
}
Following code works for me in Wicket 6:
public class MyComponent extends Panel {
...
FeedbackMessages feedback = getFeedbackMessages();
feedback.clear();

Possible bug with GWT gwtquery .live() method

I'm trying to do the following:
I want to add a specific handler for some links, denoted by a class.
$("a.link_list").live("click", new ListLinkHandler());
I need .live() instead of .bind() because new such links will be generated. (I know jQuery's .live() is deprecated in favor of .on(), but gwt-query doesn't have a .on() yet.)
I defined the handler like this (just as the gwtquery example does):
public class ListLinkHandler extends Function {
#Override
public boolean f(Event e) { [...] }
}
However, the handler method is never called when I click the links.
I can see the event listener in Chrome Dev Tools: http://screencloud.net/v/bV5V. I think it's on the body because it's a .live().
I tried using .bind() and it worked fine. The body event listener changed in a a.link_list and the handler does what it's supposed to do, but (as documented, I didn't test) not for newly created links.
I filed a bug for the .live() method, but maybe I'm doing something wrong.
Also, I have no idea how to do it without gwtquery, GWT doesn't seem to have a method for selecting elements by class, neither to continually add the listener to new elements.
It seems you are doing something wrong, but I need more code to be sure. Could you send the complete onModuleLoad code which demonstrates this wrong behavior?
I have written a quick example using live, and it works either when adding new gwt widgets or dom elements with gquery, in both Chrome and FF
public void onModuleLoad() {
$("a.link_list").live("click", new ListLinkHandler());
// Add a new link via gquery
$("<a class='link_list' href=javascript:alert('href') onClick=alert('onClick')>Click </a>").appendTo(document);
// Add a new link via gwt widgets
Anchor a = new Anchor("click");
a.setStyleName("link_list");
a.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Window.alert("clickHandler");
}
});
RootPanel.get().add(a);
}
public class ListLinkHandler extends Function {
#Override
public boolean f(Event e) {
Window.alert("live");
return true;
}
}

Making Ctrl-C copy from whichever SourceViewer has focus in Eclipse plug-in

I successfully extended the PyDev editor in Eclipse with a side-by-side display, but I can't copy the contents of the extra SourceViewer that I added. I can select some text in the display, but when I press Ctrl+C, it always copies the main PyDev editor's selected text.
I found an article on key bindings in Eclipse editors, but the code there seems incomplete and a bit out-of-date. How can I configure the copy command to copy from whichever SourceViewer has focus?
The reason I want to do this is that I've written a tool for live coding in Python, and it would be much easier for users to submit bug reports if they could just copy the display and paste it into the bug description.
David Green's article was a good start, but it took a bit of digging to make it all work. I published a full example project on GitHub, and I'll post a couple of snippets here.
The TextViewerSupport class wires up a new action handler for each command you want to delegate to the extra text viewer. If you have multiple text viewers, just instantiate a TextViewerSupport object for each of them. It wires up everything in its constructor.
public TextViewerSupport(TextViewer textViewer) {
this.textViewer = textViewer;
StyledText textWidget = textViewer.getTextWidget();
textWidget.addFocusListener(this);
textWidget.addDisposeListener(this);
IWorkbenchWindow window = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow();
handlerService = (IHandlerService) window
.getService(IHandlerService.class);
if (textViewer.getTextWidget().isFocusControl()) {
activateContext();
}
}
The activateContext() method has a list of all the commands you want to delegate, and registers a new handler for each one. This was one of the changes from David's article; his ITextEditorActionDefinitionIds has been deprecated and replaced with IWorkbenchCommandConstants.
protected void activateContext() {
if (handlerActivations.isEmpty()) {
activateHandler(ITextOperationTarget.COPY,
IWorkbenchCommandConstants.EDIT_COPY);
}
}
// Add a single handler.
protected void activateHandler(int operation, String actionDefinitionId) {
StyledText textWidget = textViewer.getTextWidget();
IHandler actionHandler = createActionHandler(operation,
actionDefinitionId);
IHandlerActivation handlerActivation = handlerService.activateHandler(
actionDefinitionId, actionHandler,
new ActiveFocusControlExpression(textWidget));
handlerActivations.add(handlerActivation);
}
// Create a handler that delegates to the text viewer.
private IHandler createActionHandler(final int operation,
String actionDefinitionId) {
Action action = new Action() {
#Override
public void run() {
if (textViewer.canDoOperation(operation)) {
textViewer.doOperation(operation);
}
}
};
action.setActionDefinitionId(actionDefinitionId);
return new ActionHandler(action);
}
The ActiveFocusControlExpression gives the new handler a high enough priority that it will replace the standard handler, and it's almost identical to David's version. However, to get it to compile, I had to add extra dependencies to my plug-in manifest: I imported packages org.eclipse.core.expressions and org.eclipse.ui.texteditor.