Merge lp:~terry-n-brown/leo-editor/free_layout into lp:leo-editor/old-trunk

Proposed by tbnorth
Status: Merged
Merged at revision: 3870
Proposed branch: lp:~terry-n-brown/leo-editor/free_layout
Merge into: lp:leo-editor/old-trunk
Diff against target: 671 lines (+623/-3)
4 files modified
leo/plugins/free_layout.py (+100/-0)
leo/plugins/leoPluginsRef.leo (+2/-1)
leo/plugins/nested_splitter.py (+509/-0)
leo/plugins/qtGui.py (+12/-2)
To merge this branch: bzr merge lp:~terry-n-brown/leo-editor/free_layout
Reviewer Review Type Date Requested Status
Edward K. Ream Pending
Review via email: mp+50460@code.launchpad.net

Description of the change

I think this can safely be merged into the trunk because the changes to qtGui.py are very minor and it's clear they have no effect unless the plugin is enabled.

To post a comment you must log in.
Revision history for this message
Edward K. Ream (edreamleo) wrote :

On Sat, Feb 19, 2011 at 1:02 PM, tbnorth <email address hidden> wrote:
> tbnorth has proposed merging lp:~terry-n-brown/leo-editor/free_layout into lp:leo-editor.

Do I need to do anything to approve this? If not, please just merge,
assuming all unit tests pass.

Edward

Revision history for this message
tbnorth (terry-n-brown) wrote :

On Tue, 22 Feb 2011 17:02:01 -0000
"Edward K. Ream" <email address hidden> wrote:

> Do I need to do anything to approve this? If not, please just merge,
> assuming all unit tests pass.

All pass 2.6/3.1, so this is in the trunk now.

If you enable the free_layout plugin there are context menus on the
panel dividers in the GUI to add panels and move panels around.

Cheers -Terry

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'leo/plugins/free_layout.py'
2--- leo/plugins/free_layout.py 1970-01-01 00:00:00 +0000
3+++ leo/plugins/free_layout.py 2011-02-19 19:01:52 +0000
4@@ -0,0 +1,100 @@
5+#@+leo-ver=5-thin
6+#@+node:tbrown.20110203111907.5519: * @file free_layout.py
7+"""Adds flexible panel layout through context menus on the handles between panels.
8+Requires Qt.
9+"""
10+#@+others
11+#@+node:tbrown.20110203111907.5520: ** declarations
12+__version__ = '0.1'
13+#
14+# 0.1 - initial release - TNB
15+
16+import leo.core.leoGlobals as g
17+
18+g.assertUi('qt')
19+
20+from PyQt4 import QtCore, QtGui, Qt
21+
22+from leo.plugins.nested_splitter import NestedSplitter
23+#@+node:tbrown.20110203111907.5521: ** init
24+def init():
25+
26+ if g.app.gui.guiName() != "qt":
27+ return False
28+
29+ g.registerHandler('after-create-leo-frame',onCreate)
30+ # can't use before-create-leo-frame because Qt dock's not ready
31+ g.plugin_signon(__name__)
32+
33+ return True
34+#@+node:tbrown.20110203111907.5522: ** onCreate
35+def onCreate(tag, keys):
36+
37+ c = keys.get('c')
38+ if not c: return
39+
40+ NestedSplitter.enabled = True
41+
42+ # define menu callbacks here where c is in scope
43+ def offer_tabs(menu, splitter, index, button_mode):
44+
45+ if not button_mode:
46+ return
47+
48+ top_splitter = c.frame.top.splitter_2.top()
49+ logTabWidget = top_splitter.findChild(QtGui.QWidget, "logTabWidget")
50+
51+ for n in range(logTabWidget.count()):
52+
53+ act = QtGui.QAction("Add "+logTabWidget.tabText(n), splitter)
54+
55+ def wrapper(w=logTabWidget.widget(n), s=splitter,
56+ t=logTabWidget.tabText(n)):
57+ w.setHidden(False)
58+ w._is_from_tab = t
59+ s.replace_widget(s.widget(index), w)
60+ act.connect(act, Qt.SIGNAL('triggered()'), wrapper)
61+ menu.addAction(act)
62+
63+ def offer_viewrendered(menu, splitter, index, button_mode):
64+
65+ if not button_mode:
66+ return
67+
68+ if hasattr(c, "viewrendered") and c.viewrendered:
69+
70+ act = QtGui.QAction("Add viewrendered", splitter)
71+
72+ def wrapper(w=c.viewrendered, s=splitter):
73+ s.replace_widget(s.widget(index), w)
74+ act.connect(act, Qt.SIGNAL('triggered()'), wrapper)
75+ menu.addAction(act)
76+
77+
78+ splitter = c.frame.top.splitter_2.top()
79+
80+ # register menu callbacks
81+ splitter.register(offer_tabs)
82+ splitter.register(offer_viewrendered)
83+
84+ # when NestedSplitter disposes of children, it will either close
85+ # them, or move them to another designated widget. Here we set
86+ # up two designated widgets
87+
88+ logTabWidget = splitter.findChild(QtGui.QWidget, "logTabWidget")
89+ splitter.root.holders['_is_from_tab'] = logTabWidget
90+ splitter.root.holders['_is_permanent'] = splitter
91+
92+ # allow body and tree widgets to be "removed" to tabs on the log tab panel
93+ bodyWidget = splitter.findChild(QtGui.QFrame, "bodyFrame")
94+ bodyWidget._is_from_tab = "Body"
95+ treeWidget = splitter.findChild(QtGui.QFrame, "outlineFrame")
96+ treeWidget._is_from_tab = "Tree"
97+ # also the other tabs will have _is_from_tab set on them by the
98+ # offer_tabs menu callback above
99+
100+ # if the log tab panel is removed, move it back to the top splitter
101+ logWidget = splitter.findChild(QtGui.QFrame, "logFrame")
102+ logWidget._is_permanent = True
103+#@-others
104+#@-leo
105
106=== modified file 'leo/plugins/leoPluginsRef.leo'
107--- leo/plugins/leoPluginsRef.leo 2011-02-13 18:11:37 +0000
108+++ leo/plugins/leoPluginsRef.leo 2011-02-19 19:01:52 +0000
109@@ -76,8 +76,9 @@
110 expanded="tbrown.20090119215428.9,tbrown.20090119215428.11,tbrown.20090119215428.19,tbrown.20090119215428.30,tbrown.20090119215428.40,"><vh>@file todo.py</vh></v>
111 <v t="tbrown.20100318101414.5990"
112 expanded="tbrown.20100318101414.5997,"><vh>@file viewrendered.py</vh></v>
113-<v t="tbrown.20090206153748.1" a="E"
114+<v t="tbrown.20090206153748.1"
115 expanded="bob.20110119123023.7395,bob.20110119123023.7400,bob.20110121161547.3424,bob.20110119123023.7408,bob.20110120111825.3352,bob.20110121113659.3412,bob.20110121113659.3414,bob.20110121113659.3413,"><vh>@file graphcanvas.py</vh></v>
116+<v t="tbrown.20110203111907.5519" a="E"><vh>@file free_layout.py</vh></v>
117 </v>
118 <v t="edream.110203113231.667"><vh>Commands &amp; directives</vh>
119 <v t="edream.110203113231.741"><vh>@file add_directives.py</vh></v>
120
121=== added file 'leo/plugins/nested_splitter.py'
122--- leo/plugins/nested_splitter.py 1970-01-01 00:00:00 +0000
123+++ leo/plugins/nested_splitter.py 2011-02-19 19:01:52 +0000
124@@ -0,0 +1,509 @@
125+import sys
126+from inspect import isclass
127+from PyQt4 import QtGui, QtCore, Qt
128+from PyQt4.QtCore import Qt as QtConst
129+class DemoWidget(QtGui.QWidget):
130+
131+ count = 0
132+
133+
134+ def __init__(self, parent=None, color=None):
135+
136+ QtGui.QWidget.__init__(self, parent)
137+
138+ self.setLayout(QtGui.QVBoxLayout())
139+ self.layout().setContentsMargins(QtCore.QMargins(0,0,0,0))
140+ self.layout().setSpacing(0)
141+
142+ text = QtGui.QTextEdit()
143+ self.layout().addWidget(text)
144+ DemoWidget.count += 1
145+ text.setPlainText("#%d" % DemoWidget.count)
146+
147+ button_layout = QtGui.QHBoxLayout()
148+ button_layout.setContentsMargins(QtCore.QMargins(5,5,5,5))
149+ self.layout().addLayout(button_layout)
150+
151+
152+ button_layout.addWidget(QtGui.QPushButton("Go"))
153+ button_layout.addWidget(QtGui.QPushButton("Stop"))
154+
155+ if color:
156+ self.setStyleSheet("background-color: %s;"%color)
157+
158+class NestedSplitterChoice(QtGui.QWidget):
159+
160+ def __init__(self, parent=None):
161+
162+ QtGui.QWidget.__init__(self, parent)
163+
164+ self.setLayout(QtGui.QVBoxLayout())
165+
166+ button = QtGui.QPushButton("Action", parent=self)
167+ self.layout().addWidget(button)
168+
169+ button.setContextMenuPolicy(QtConst.CustomContextMenu)
170+ button.connect(button,
171+ Qt.SIGNAL('customContextMenuRequested(QPoint)'),
172+ lambda pnt: self.parent().choice_menu(self, pnt))
173+ button.connect(button,
174+ Qt.SIGNAL('clicked()'),
175+ lambda: self.parent().choice_menu(self, button.pos()))
176+
177+class NestedSplitterHandle(QtGui.QSplitterHandle):
178+
179+ def __init__(self, owner):
180+ QtGui.QSplitterHandle.__init__(self, owner.orientation(), owner)
181+
182+ self.setStyleSheet("background-color: green;")
183+
184+ self.setContextMenuPolicy(QtConst.CustomContextMenu)
185+ self.connect(self,
186+ Qt.SIGNAL('customContextMenuRequested(QPoint)'),
187+ self.splitter_menu)
188+
189+ def splitter_menu(self, pos):
190+
191+ splitter = self.splitter()
192+
193+ if not splitter.enabled:
194+ return
195+
196+ splitter = self.splitter()
197+ index = splitter.indexOf(self)
198+
199+ widget, neighbour, count = splitter.handle_context(index)
200+
201+ lr = 'left', 'right'
202+ ab = 'above', 'below'
203+ split_dir = 'vertically'
204+ if self.orientation() == QtConst.Vertical:
205+ lr, ab = ab, lr
206+ split_dir = 'horizontally'
207+
208+ color = '#729fcf', '#f57900'
209+ sheet = []
210+ for i in 0,1:
211+ sheet.append(widget[i].styleSheet())
212+ widget[i].setStyleSheet(sheet[-1]+"\nborder: 2px solid %s;"%color[i])
213+
214+ menu = QtGui.QMenu()
215+
216+ # insert
217+ act = QtGui.QAction("Insert", self)
218+ act.setObjectName('insert')
219+ act.connect(act, Qt.SIGNAL('triggered()'),
220+ lambda: splitter.insert(index))
221+ menu.addAction(act)
222+
223+ # swap
224+ act = QtGui.QAction("Swap %d %s %d %s" % (count[0], lr[0], count[1], lr[1]), self)
225+ act.setObjectName('swap')
226+ act.connect(act, Qt.SIGNAL('triggered()'),
227+ lambda: splitter.swap(index))
228+ menu.addAction(act)
229+
230+ # rotate
231+ act = QtGui.QAction("Rotate all", self)
232+ act.setObjectName('rotate')
233+ act.connect(act, Qt.SIGNAL('triggered()'), splitter.rotate)
234+ menu.addAction(act)
235+
236+ # remove, +0/-1 reversed, we need to test the one that remains
237+
238+ # first see if a parent has more than two splits (we could be a sole
239+ # surviving child)
240+ max_parent_splits = 0
241+ up = splitter.parent()
242+ while isinstance(up, NestedSplitter):
243+ max_parent_splits = max(max_parent_splits, up.count())
244+ up = up.parent()
245+ if max_parent_splits >= 2:
246+ break # two is enough
247+
248+ for i in 0,1:
249+
250+ keep = splitter.widget(index)
251+ cull = splitter.widget(index-1)
252+ if (max_parent_splits >= 2 or # more splits upstream
253+ splitter.count() > 2 or # 3+ splits here, or 2+ downstream
254+ neighbour[not i] and neighbour[not i].max_count() >= 2):
255+ act = QtGui.QAction("Remove %d %s"%(count[i], lr[i]), self)
256+ act.setObjectName('remove %d'%i)
257+ def wrapper(i=i): splitter.remove(index, i)
258+ act.connect(act, Qt.SIGNAL('triggered()'), wrapper)
259+ menu.addAction(act)
260+
261+ # only offer split if not already split
262+ for i in 0,1:
263+ if (not neighbour[i] or neighbour[i].count() == 1):
264+ act = QtGui.QAction("Split %s %s"%(lr[i], split_dir), self)
265+ act.setObjectName('split %d'%i)
266+ def wrapper(i=i): splitter.split(index, i)
267+ act.connect(act, Qt.SIGNAL('triggered()'), wrapper)
268+ menu.addAction(act)
269+
270+ # mark
271+ for i in 0,1:
272+ act = QtGui.QAction("Mark %d %s"%(count[i], lr[i]), self)
273+ act.setObjectName('mark %d'%i)
274+ def wrapper(i=i): splitter.mark(index, i)
275+ act.connect(act, Qt.SIGNAL('triggered()'), wrapper)
276+ menu.addAction(act)
277+
278+ # swap with mark
279+ if splitter.root.marked:
280+ for i in 0,1:
281+ if not splitter.invalid_swap(widget[i], splitter.root.marked[2]):
282+ act = QtGui.QAction("Swap %d %s with marked"%(count[i], lr[i]), self)
283+ act.setObjectName('swap mark %d'%i)
284+ def wrapper(i=i): splitter.swap_with_marked(index, i)
285+ act.connect(act, Qt.SIGNAL('triggered()'), wrapper)
286+ menu.addAction(act)
287+
288+ # add
289+ for i in 0,1:
290+ if (not isinstance(splitter.parent(), NestedSplitter) or
291+ splitter.parent().indexOf(splitter) ==
292+ [0,splitter.parent().count()-1][i]):
293+ act = QtGui.QAction("Add %s"%ab[i], self)
294+ act.setObjectName('add %d'%i)
295+ def wrapper(i=i): splitter.add(i)
296+ act.connect(act, Qt.SIGNAL('triggered()'), wrapper)
297+ menu.addAction(act)
298+
299+ for cb in splitter.root.callbacks:
300+ cb(menu, splitter, index, button_mode=False)
301+
302+ menu.exec_(self.mapToGlobal(pos))
303+
304+ for i in 0,1:
305+ widget[i].setStyleSheet(sheet[i])
306+
307+class NestedSplitter(QtGui.QSplitter):
308+
309+ enabled = True
310+ # allow special behavior to be turned of at import stage
311+ # useful if other code must run to set up callbacks, that
312+ # other code can re-enable
313+
314+ other_orientation = {
315+ QtConst.Vertical: QtConst.Horizontal,
316+ QtConst.Horizontal: QtConst.Vertical
317+ }
318+
319+
320+ def __init__(self, parent=None, orientation=QtConst.Horizontal, root=None):
321+ QtGui.QSplitter.__init__(self, parent=parent, orientation=orientation)
322+
323+ if not root:
324+ root = self.top()
325+ if root == self:
326+ root.marked = None
327+ root.callbacks = []
328+ root.holders = {}
329+ self.root = root
330+ def add(self, side):
331+
332+ orientation = self.other_orientation[self.orientation()]
333+
334+ if isinstance(self.parent(), NestedSplitter):
335+ # don't add new splitter if not needed, i.e. we're the
336+ # only child of a previosly more populated splitter
337+
338+ self.parent().insertWidget(
339+ self.parent().indexOf(self) + side - 1 + 1,
340+ NestedSplitterChoice(self))
341+
342+ elif self.parent().layout():
343+
344+ new = NestedSplitter(None, orientation=orientation,
345+ root=self.root)
346+ # parent set by insertWidget() below
347+
348+ old = self
349+
350+ pos = self.parent().layout().indexOf(old)
351+
352+ self.parent().layout().insertWidget(pos, new)
353+
354+ new.addWidget(old)
355+ new.insertWidget(side, NestedSplitterChoice(new))
356+
357+ else:
358+ # fail - parent is not NestedSplitter and has no layout
359+ pass
360+ def choice_menu(self, button, pos):
361+
362+ menu = QtGui.QMenu()
363+
364+ if self.root.marked and not self.invalid_swap(button, self.root.marked[3]):
365+ an_item = True
366+ act = QtGui.QAction("Move marked here", self)
367+ act.connect(act, Qt.SIGNAL('triggered()'),
368+ lambda: self.replace_widget(button, self.root.marked[3]))
369+ menu.addAction(act)
370+
371+ for cb in self.root.callbacks:
372+ cb(menu, self, self.indexOf(button), button_mode=True)
373+
374+ if menu.isEmpty():
375+ act = QtGui.QAction("Nothing marked, and no options", self)
376+ menu.addAction(act)
377+
378+ menu.exec_(button.mapToGlobal(pos))
379+ def close_or_keep(self, widget):
380+
381+ if widget is None:
382+ return
383+
384+ for k in self.root.holders:
385+ if hasattr(widget, k):
386+ holder = self.root.holders[k]
387+ if hasattr(holder, "addTab"):
388+ holder.addTab(widget, getattr(widget,k))
389+ else:
390+ holder.addWidget(widget)
391+ break
392+ else:
393+ widget.close()
394+ widget.deleteLater()
395+ def contains(self, widget):
396+ """check if widget is a descendent of self"""
397+
398+ for i in range(self.count()):
399+ if widget == self.widget(i):
400+ return True
401+ if isinstance(self.widget(i), NestedSplitter):
402+ if self.widget(i).contains(widget):
403+ return True
404+
405+ return False
406+
407+ def createHandle(self, *args, **kargs):
408+
409+ return NestedSplitterHandle(self)
410+
411+ def handle_context(self, index):
412+
413+ widget = [
414+ self.widget(index-1),
415+ self.widget(index),
416+ ]
417+
418+ neighbour = [ (i if isinstance(i, NestedSplitter) else None)
419+ for i in widget ]
420+
421+ count = []
422+ for i in 0,1:
423+ if neighbour[i]:
424+ l = [ii.count() for ii in neighbour[i].self_and_descendants()]
425+ n = sum(l) - len(l) + 1 # count leaves, not splitters
426+ count.append(n)
427+ else:
428+ count.append(1)
429+
430+ return widget, neighbour, count
431+ def insert(self, index):
432+
433+ self.insertWidget(index, NestedSplitterChoice(self))
434+
435+ def invalid_swap(self, w0, w1):
436+ if w0 == w1:
437+ return True
438+ if (isinstance(w0, NestedSplitter) and w0.contains(w1) or
439+ isinstance(w1, NestedSplitter) and w1.contains(w0)):
440+ return True
441+ return False
442+
443+ def mark(self, index, side):
444+ self.root.marked = (self, index, side-1,
445+ self.widget(index+side-1))
446+ def max_count(self):
447+ """find max widgets in this and child splitters"""
448+
449+ return max([i.count() for i in self.self_and_descendants()])
450+
451+ def register(self, cb):
452+
453+ self.root.callbacks.append(cb)
454+ def remove(self, index, side):
455+
456+ widget = self.widget(index+side-1)
457+
458+ # clear marked if it's going to be deleted
459+ if (self.root.marked and (self.root.marked[3] == widget or
460+ isinstance(self.root.marked[3], NestedSplitter) and
461+ self.root.marked[3].contains(widget))):
462+ self.root.marked = None
463+
464+ # send close signal to all children
465+ if isinstance(widget, NestedSplitter):
466+
467+ count = widget.count()
468+
469+ for splitter in widget.self_and_descendants():
470+ for i in range(splitter.count()):
471+ self.close_or_keep(splitter.widget(i))
472+
473+ if count <= 0:
474+ widget.deleteLater()
475+
476+ else:
477+ self.close_or_keep(widget)
478+
479+ def replace_widget(self, old, new):
480+
481+ self.insertWidget(self.indexOf(old), new)
482+ old.deleteLater()
483+
484+ def rotate(self, descending=False):
485+ """Change orientation - current rotates entire hierachy, doing less
486+ is visually confusing because you end up with nested splitters with
487+ the same orientation - avoiding that would mean doing rotation by
488+ inserting out widgets into our ancestors, etc.
489+ """
490+
491+ for i in self.top().self_and_descendants():
492+ if i.orientation() == QtConst.Vertical:
493+ i.setOrientation(QtConst.Horizontal)
494+ else:
495+ i.setOrientation(QtConst.Vertical)
496+ def self_and_descendants(self):
497+ """Yield self and all **NestedSplitter** descendants"""
498+
499+ for i in range(self.count()):
500+ if isinstance(self.widget(i), NestedSplitter):
501+ for w in self.widget(i).self_and_descendants():
502+ yield w
503+ yield self
504+ def split(self, index, side):
505+
506+ old = self.widget(index+side-1)
507+
508+ if isinstance(old, NestedSplitter):
509+ old.addWidget(NestedSplitterChoice(self))
510+ return
511+
512+ orientation = self.other_orientation[self.orientation()]
513+
514+ new = NestedSplitter(self, orientation=orientation, root=self.root)
515+ self.insertWidget(index+side-1, new)
516+ new.addWidget(old)
517+ new.addWidget(NestedSplitterChoice(self))
518+ def swap(self, index):
519+
520+ self.insertWidget(index-1, self.widget(index))
521+
522+ def swap_with_marked(self, index, side):
523+
524+ osplitter, oidx, oside, ow = self.root.marked
525+
526+ idx = index+side-1
527+ # convert from handle index to widget index
528+ # 1 already subtracted from oside in mark()
529+ w = self.widget(idx)
530+
531+ if self.invalid_swap(w, ow):
532+ # print 'Invalid swap'
533+ return
534+
535+ self.insertWidget(idx, ow)
536+ osplitter.insertWidget(oidx, w)
537+
538+ self.root.marked = self, self.indexOf(ow), 0, ow
539+ def top(self):
540+ """find top widget, which is not necessarily root"""
541+
542+ top = self
543+ while isinstance(top.parent(), NestedSplitter):
544+ top = top.parent()
545+
546+ return top
547+if __name__ == "__main__":
548+
549+ def demo_nest(splitter):
550+ orientation = splitter.other_orientation[splitter.orientation()]
551+ x = NestedSplitter(splitter, root=splitter.root,
552+ orientation=orientation)
553+ s = [x]
554+ for i in range(4):
555+ orientation = splitter.other_orientation[orientation]
556+ ns = []
557+ for j in s:
558+ j.addWidget(DemoWidget())
559+ ns.append(NestedSplitter(splitter, orientation=orientation,
560+ root=splitter.root))
561+ j.addWidget(ns[-1])
562+ s = ns
563+
564+ for i in s:
565+ i.addWidget(DemoWidget())
566+
567+ return x
568+
569+ def callback(menu, splitter, index, button_mode):
570+
571+ if not button_mode:
572+ return
573+
574+ act = QtGui.QAction("Add DemoWidget", splitter)
575+ def wrapper():
576+ splitter.replace_widget(splitter.widget(index),
577+ DemoWidget(splitter))
578+ act.connect(act, Qt.SIGNAL('triggered()'), wrapper)
579+ menu.addAction(act)
580+
581+ act = QtGui.QAction("Add DemoWidget Nest", splitter)
582+ def wrapper():
583+ splitter.replace_widget(splitter.widget(index),
584+ demo_nest(splitter))
585+ act.connect(act, Qt.SIGNAL('triggered()'), wrapper)
586+ menu.addAction(act)
587+
588+ # example - remove "Remove" commands from handle context menu
589+ def callback2(menu, splitter, index, button_mode):
590+
591+ if button_mode:
592+ return
593+
594+ for i in [i for i in menu.actions()
595+ if str(i.objectName()).startswith('remove')]:
596+ menu.removeAction(i)
597+
598+ # more complex example only removing remove action for particular target
599+ def dont_close_special(menu, splitter, index, button_mode):
600+
601+ if button_mode:
602+ return
603+
604+ widget, neighbour, count = splitter.handle_context(index)
605+
606+ for i in 0,1:
607+ if (widget[i] == special or
608+ neighbour[i] and neighbour[i].contains(special)):
609+
610+ for a in [a for a in menu.actions()
611+ if a.objectName() == "remove %d"%i]:
612+ menu.removeAction(i)
613+
614+
615+ app = Qt.QApplication(sys.argv)
616+
617+ wdg = DemoWidget()
618+ wdg2 = DemoWidget()
619+
620+ splitter = NestedSplitter()
621+ splitter.addWidget(wdg)
622+ splitter.addWidget(wdg2)
623+
624+ splitter.register(callback)
625+ # splitter.register(callback2)
626+
627+ holder = QtGui.QWidget()
628+ holder.setLayout(QtGui.QVBoxLayout())
629+ holder.layout().setContentsMargins(QtCore.QMargins(0,0,0,0))
630+ holder.layout().addWidget(splitter)
631+ holder.show()
632+
633+ app.exec_()
634
635=== modified file 'leo/plugins/qtGui.py'
636--- leo/plugins/qtGui.py 2011-02-19 18:54:19 +0000
637+++ leo/plugins/qtGui.py 2011-02-19 19:01:52 +0000
638@@ -62,6 +62,16 @@
639 print('\nqtGui.py: can not import Qt\nUse "launchLeo.py --gui=tk" to force Tk')
640 raise
641
642+try:
643+ from nested_splitter import NestedSplitter
644+ splitter_class = NestedSplitter
645+
646+ # disable special behavior, turned back on by associated plugin,
647+ # if the plugin's loaded
648+ NestedSplitter.enabled = False
649+except ImportError:
650+ splitter_class = QtGui.QSplitter
651+
652 # remove scintilla dep for now
653 if 0:
654 try:
655@@ -1978,7 +1988,7 @@
656 vLayout = self.createVLayout(parent,'mainVLayout',margin=3)
657
658 # Splitter two is the "main" splitter, containing splitter.
659- splitter2 = QtGui.QSplitter(parent)
660+ splitter2 = splitter_class(parent)
661 splitter2.setOrientation(QtCore.Qt.Vertical)
662 splitter2.setObjectName("splitter_2")
663
664@@ -1986,7 +1996,7 @@
665 QtCore.SIGNAL("splitterMoved(int,int)"),
666 self.onSplitter2Moved)
667
668- splitter = QtGui.QSplitter(splitter2)
669+ splitter = splitter_class(splitter2)
670 splitter.setOrientation(QtCore.Qt.Horizontal)
671 splitter.setObjectName("splitter")
672

Subscribers

People subscribed via source and target branches

to status/vote changes: