Switch between first sheet(tab) and previous sheet on sublime text - plugins

I am trying to program a plugin for myself to switch tab automatically. When I change to other window, the first tab will be shown. When I change back to sublime, the editng tab will show up. I got the following code, which can switch to the first tab. But when I get back to sublime text , it hangs , instead of switching back the tab. Anything I have miss understand with sheets? Thanks!
import sublime
import sublime_plugin
class ShowSheets(sublime_plugin.EventListener):
"""
Display the name of the current project in the status bar.
"""
orisheet = 0
def show_1st(self,view):
if view.window() is None:
return
self.orisheet = view.window().active_sheet()
firstsheet = view.window().sheets()
view.window().focus_sheet(firstsheet[0])
def show_original(self,view):
if view.window() is None:
return
if self.orisheet == 0:
return
view.window().focus_sheet(self.orisheet)
def on_activated(self, view):
self.show_original (view)
def on_deactivated(self, view):
self.show_1st (view)

This is because you have created an infinite callback loop - on_activated and on_deactivated are called when a tab gains or loses the focus.
Thus, when the ST window loses the focus, on_deactivated runs once. Then, when the ST window regains the focus, it calls on_activated once. Then, your code switches the active tab, so on_deactivated and on_activated are executed again, and the cycle repeats indefinitely.
Probably you could work around this by checking which tab is already active, and don't set the focus to the currently active tab. But, you may find that your code will just prevent you from ever being able to switch tab, because there is no real way to tell when a Window loses focus vs. when the active tab has changed.

Related

TreeView multiple selection does not work correctly after changing selection without UI

This is potentially a bug, though perhaps I'm misunderstanding something.
Brief description
Basically, I have found that using "Shift+Arrows" to do multiple selection in a Gtk.TreeView does not work correctly after changing the selection using Gtk.TreeSelection.select_iter. On the other hand, if you change the selection by clicking on a row and then pressing "Shift+Arrows", the selection behaves as one would expect.
I should note that if you change the selected row by calling Gtk.TreeSelection.select_iter, the UI updates as you would expect and calling Gtk.TreeSelection.get_selected_rows() returns the rows it should. It's only when you then try to select multiple rows using the arrow keys that you get strange behavior.
This is perhaps best illustrated in this self contained example, which I've tried to make as simple as possible:
Code
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class TreeViewBug(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.connect('destroy', Gtk.main_quit)
# Create model consisting of row path and a name
self.treeModel = Gtk.ListStore(int, str)
self.treeModel.append([0, 'alice'])
self.treeModel.append([1, 'bob'])
self.treeModel.append([2, 'chad'])
self.treeModel.append([3, 'dan'])
self.treeModel.append([4, 'emma'])
self.treeView = Gtk.TreeView()
self.treeView.append_column(Gtk.TreeViewColumn('path', Gtk.CellRendererText(), text=0))
self.treeView.append_column(Gtk.TreeViewColumn('name', Gtk.CellRendererText(), text=1))
self.treeView.set_model(self.treeModel)
# Allow for multiple selection
self.treeView.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
self.add(self.treeView)
def run(self):
self.show_all()
# Focus the TreeView so we can test multiple select via keyboard without clicking on a row
self.treeView.grab_focus()
# Manually change the selected row to the row with "chad"
chadIter = self.treeModel[2].iter
self.treeView.get_selection().select_iter(chadIter)
print('Press "Shift+Down" and see what happens')
print(' it should select "chad, dan", but instead it selects "bob, chad"')
print('Afterwards, try clicking on "chad" and then pressing Shift+Down. It should behave normally')
Gtk.main()
if __name__ == '__main__':
tv = TreeViewBug()
tv.run()
Things I've tried
I initially encountered the bug when my code changed the selected row via Gtk.TreeSelection.select_iter in response to a button click.
I've also tried:
adding a custom select function (Gtk.TreeSelection.set_select_function)
clearing the selection before changing it (Gtk.TreeSelection.unselect_all)
changing the selection asynchronously (GLib.idle_add).
redrawing TreeView after changing selection
Speculations
I'm guessing that TreeView/TreeViewSelection has some internal state variable tracking selection and row that, for some reason, isn't getting properly updated when TreeSelection.select_iter is called. These variables are probably related to UI features, because TreeSelection.get_selected_rows still works properly. Also it makes sense the UI would need additional state information since the UI logic of multiple selection depends on previous UI interaction (Shift+Down behaves differently when extending a selection depending on whether you initially selected upwards or downwards)
Because a Gtk.TreeView uses MVC, you actually need to set the cursor of the treeview. This may affect the rest of the program, depending on what you are doing. Example:
#chadIter = self.treeModel[2].iter
#self.treeView.get_selection().select_iter(chadIter)
path = 2
column = self.treeView.get_column(0)
edit = False
self.treeView.set_cursor(path, column, edit)

tabcontrol page not updated

In my winfom program I have a function that change the tabpage when I hit a key.
On tabcontrol indexchanged I check for some parametre and if they are not correct I change the tabpage to the first tab.
If I click on the page with the mouse the tabpage changed to the first tab with the correct content.
If I click a key and run this code "tcOrdre.SelectedTab = tpOrdre;" it changes the tab back to the first but still showing the content of the selected one.
In SelectedIndexChanged is use this code:
MessageBox.Show("Der skal vælges en ordre først"); // Show a messagebox
tcOrdre.SelectedTab = tpOrdreListe; // change tap to first
If I use the mouse then SelectIndexChanged get called when I run:
tcOrdre.SelectedTab = tpOrdreListe; // change tap to first
the SelectedIndexChanged function is called again and the content is okay.
But if I use the key to change index the SelectedIndexChanged does not get called Again and the content never change. Only the tab in the top change to the first one.
I hope someone can help me.
I found the solution.
All I have to do is call this line.
this.BeginInvoke(new Action(() => tcOrdre.SelectTab(0)));
and not tcOrdre.SelectedTab = tpOrdreListe;
And everything Works fine.

Text Editor in eclipse plugin is not properly executed

I have created multipage HTML editor in which one tab has text editor. I have set the global action handler to the action bar for undo / redo actions in the source editor. Whenever I am adding something in the source editor then undo it, it is not returning the same code in the first attempt. It is completing in the second attempt. Can anyone help me to solve this issue.
In the main editor override the setFocus() method and in this method call the following method of source editor.
public void setUndoRedoActionHandlers() {
final IActionBars actionBars = getEditorSite().getActionBars();
actionBars.setGlobalActionHandler(ActionFactory.UNDO.getId(),
mUndoAction);
actionBars.setGlobalActionHandler(ActionFactory.REDO.getId(),
mRedoAction);
actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(),
mDeleteAction);
actionBars.setGlobalActionHandler(
ITextEditorActionConstants.DELETE_LINE, mDeleteLineAction);
actionBars.updateActionBars();
}
Thanks
Are you sure that you set global actions by overriding setFocus()? Look at this : https://wiki.eclipse.org/FAQ_How_do_I_enable_global_actions_such_as_Cut,_Paste,_and_Print_in_my_editor%3F
It says they need to be set inside method setActiveEditor()
The reason I guess why you are seeing it working second time is - When the first time you click your editor gets focus and setFocus is called and only then the global actions are set. Then second time it will work because the actions are now set.

QCompleter and Tab key

I'm trying to make a Completion when pressing tab, you get the first completion of all possibilities.
But, in a QWidget-based main window, pressing tab will make that QLineEdit lost focus, and completion popup hides after that.
Is there a way to fix it ?
Have you tried to subclass QLineEdit and intercept the key press event?
Alternatively you could set up an event filter.
Whew. It took me some time to figure this out :) Multiple times I have tried to solve this problem, but always gave up. Now, I dug enough to find the answer.
OP, please pardon me, because the code here is Python, but should be understandable and work for C++ as well.
Basically, the problem I had was "how to select an entry in the QCompleter"; I didn't notice before, but the answer is in the popup() method. QCompleter works with a model and a view, which contains the things to show.
You can change the current row as you wish, then get the index of that row in the model, then select it in the pop-up.
In my code, I subclassed QLineEdit, created a tabPressed signal which is emitted every time Tab is pressed. Then, connected this signal to a method of the same class which does this:
get the current index;
select the index in the popup;
advance to the next row.
As implementation, this is very trivial, but for my current purpose this is enough. Here's the skeleton (just for the tab part, it's missing the model and everything else).
class MyLineEdit(QLineEdit):
tabPressed = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
self._compl = QCompleter()
self.tabPressed.connect(self.next_completion)
def next_completion(self):
index = self._compl.currentIndex()
self._compl.popup().setCurrentIndex(index)
start = self._compl.currentRow()
if not self._compl.setCurrentRow(start + 1):
self._compl.setCurrentRow(0)
def event(self, event):
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
self.tabPressed.emit()
return True
return super().event(event)
You may need to adjust/fix few things, but this is the basic idea.
EDIT:
For details see
http://www.qtcentre.org/threads/23518-How-to-change-completion-rule-of-QCompleter
There's a little issue: when Return is pressed, the things don't work properly. Maybe you can find a solution to this problem in the link above, or in the referenced resources therein. I'll fix this in the next few days and update this answer.
There is probably a better solution but one that comes to mind is to change the focus policy for all other widgets on the form to something that doesn't include "tab" focus. The only options that don't use the tab key are Qt::ClickFocus and Qt::NoFocus.

wxPython: How to handle event binding and Show() properly

I'm just starting out with wxPython and this is what I would like to do:
a) Show a Frame (with Panel inside it) and a button on that panel.
b) When I press the button, a dialog box pops up (where I can select from a choice).
c) When I press ok on dialog box, the dialog box should disappear (destroyed), but the original Frame+Panel+button are still there.
d) If I press that button again, the dialog box will reappear.
My code is given below. Unfortunately, I get the reverse effect. That is,
a) The Selection-Dialog box shows up first (i.e., without clicking on any button since the TopLevelframe+button is never shown).
b) When I click ok on dialog box, then the frame with button appears.
c) Clicking on button again has no effect (i.e., dialog box does not show up again).
What am I doing wrong ? It seems that as soon as the frame is initialized (even before the .Show() is called), the dialog box is initialized and shown automatically.
I am doing this using Eclipse+Pydev on WindowsXP with Python 2.6
============File:MainFile.py===============
import wx
import MyDialog #This is implemented in another file: MyDialog.py
class TopLevelFrame(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,"Test",size=(300,200))
panel=wx.Panel(self)
button=wx.Button(panel, label='Show Dialog', pos=(130,20), size=(60,20))
# Bind EVENTS --> HANDLERS.
button.Bind(wx.EVT_BUTTON, MyDialog.start(self))
# Run the main loop to start program.
if __name__=='__main__':
app=wx.PySimpleApp()
TopLevelFrame(parent=None, id=-1).Show()
app.MainLoop()
============File:MyDialog.py===============
import wx
def start(parent):
inputbox = wx.SingleChoiceDialog(None,'Choose Fruit', 'Selection Title',
['apple','banana','orange','papaya'])
if inputbox.ShowModal()==wx.ID_OK:
answer = inputbox.GetStringSelection()
inputbox.Destroy()
There are a number of ways to do this, but to make the least number of changes to your code,
Change def start(parent): to
def start(parent, evt):
And change button.Bind(wx.EVT_BUTTON, MyDialog.start(self)) to
button.Bind(wx.EVT_BUTTON, lambda evt: MyDialog.start(self, evt))
That is, the second argument in Bind needs to be a function that takes and event, and you need to create the dialog box when the button is clicked. lambda makes this a function that also takes parent and evt (you can also use functools.partial for version >2.5), and then when the button is clicked, start will be called to create the dialog.
I'm not quite sure what's going on in your code, but it seems that you're calling start and creating the dialog in your initial call to Bind, and then passing the return value from start, None to Bind.
Note 1
In more detail, the reason to use the lambda here is that Bind should have a form like Bind(event, handler) where event is a wx.PyEventBinder, like wx.EVT_BUTTON, and handler is a function like foo(evt) where evt is a wx.Event or wx.CommandEvent. (There's no recursion here, as you're just saying what to do when something happens, but that thing hasn't happened yet, so the event hasn't been created. When the event does happen, it will be represented by a wx.Event, which will have information about the event, like where the mouse was when it was clicked, etc.)
Note 2
In my answer I tried to answer your question with minimal changes as I thought that would be easiest. Maybe the code below is more clear (and maybe it's generally clearest to handle events within the widget that creates them):
def start2(parent):
inputbox = wx.SingleChoiceDialog(parent,'Choose Fruit', 'Selection Title',
['apple','banana','orange','papaya'])
if inputbox.ShowModal()==wx.ID_OK:
answer = inputbox.GetStringSelection()
inputbox.Destroy()
class TopLevelFrame2(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,"Test",size=(300,200))
panel=wx.Panel(self)
button=wx.Button(panel, label='Show Dialog', pos=(130,20), size=(60,20))
# Bind EVENTS --> HANDLERS.
button.Bind(wx.EVT_BUTTON, self.OnClick)
def OnClick(self, evt):
start2(self)