Onscreen IDE & dynamic instant update [_v0.5.4_]


#4

UPDATE :

  1. able to load files, create new file, and save file as
  2. supports case change, to uppercase, lowercase, and swapcase
  3. besides rebind process exceptions handling, now able to handle runtime continuous tasks exceptions too, done by wrapping taskMgr.run(), and if the faulty task is in the tasks list, it would be removed, so it wouldn’t halt Panda. Practically, you will never get dropped to Python prompt at all. To demonstrate this, I split the jacks into a separate module : jackClass.py. In there, I used doMethodLater, which will be called 5 seconds later, after the scene get started. That method uses Task, which is not imported, I commented out its import line (line #2). So after 5 seconds passes by, you’ll be alerted about the error, and the module file will be set as the active document, or if it’s not loaded, it will be loaded first.

more shots :


#5

wow you are putting quite amount of work into this! Much better then the editor i made.


#6

wow wow wow-wow-wow :smiley:


#7

Looks amazing! :smiley:

Regards, Bigfoot29


#8

UPDATE:

  1. dynamic updater : there was a super huge hole in my previous updater. I hadn’t thought about it earlier. It’s the old instances replacement. The way I recreated the new instances was simply by generally call realClass(). Of course, that doesn’t work for a class which receives init arguments, which is mostly the way you need it.
    So, how if I want to rebind such a class (say class B) ? I must find its host class instances (say class A), and crush them and recreate them, so all class B instances will be created correctly and treated naturally afterward by class A instances. But how if those class A instances are part of a larger environment, which is part of another larger one ? I have to do exactly the same thing for them.
    At the end, I might need to crush the whole World class instance and recreate it anyway. So, yes that’s what I do now, directly crush World instance and recreate it everytime after any rebind process. The major inconvenience of that is the whole thing get restarted from the very beginning.

  2. dynamic updater : if there is an error in a class during instantiation after rebind, and before that erroneous point, you have attached some nodes to scenegraph, registered some events, etc, they used to get left over, alive and don’t get rolled back. It means, the next time you update the scene, you’d get another set of duplicates, models, events, lights, and everything instantiated before the broken line. So the scene would look and behave just like hell, or trash bin, sooooo ugly.
    It’s because the broken class instance doesn’t get crushed. Previously, I hadn’t figured out how to crush it, since the broken class instance isn’t saved in the caller’s locals, but only in the broken class’ locals.
    But I have found a way to crush it, by tracking the real error until the end of tracebacks chain, saving it in the caller class instance, so it can be removed altogether. So there should not be any artifact left anymore during rebind-restart process.
    To demonstrate this, uncomment this line in dyn1.py :
    [color=darkred]# self.brokenInstance=BrokenClass()
    and update it (press F9).
    You should never see the teapot created before messItUp() call in BrokenClass. What would happen is, the instance of World class, which is responsible for creating BrokenClass instance, will be crushed altogether after saving BrokenClass instance temporarily as its attribute, to ensure safety, in case the expected BrokenClass instance is used in other part of it.

  3. code completion is available, works for live objects (everything exists in builtins), all imported modules, Python keywords, and class instance attributes (the last part is still experimental and not usable yet).
    Works as you type, with stop-typing-threshold .3 second.
    It’s enabled by default, press F4 to toggle.
    Press Ctrl-Space to force it to show up if you’re not typing but want to know more about the code your cursor is on.
    Use ArrowUp/Down, PageUp/Down, and Home/End to navigate through the list.
    Press F1 to toggle the description when highlighting the available code.
    Use Ctrl-arrow up/down to navigate through the description.
    Press Enter to use the highlighted code.
    Press Esc to cancel.
    The performance to render the available codes list is poor, since I use my own text builder, which is not optimized for fast render, it’s geared towards quick show, so the faster it’s generated, the better. For 422 list items, DirectButton takes 3 seconds, plus additional 1 mysterious second. DirectLabel takes 2.3 seconds. Then I decided to use my own text builder, as for the script’s text, since I don’t need any cosmetics part. The result is it takes only 0.15 second for the same 422 items. In the future, I might use RTT too for it, just like what I do for the code description, which uses 3 pages cameras.

  4. before I released this in the 1st place, I dropped pixel-perfect text rendering for a funny reason. Somehow, some letter’s vertical edge or corner vanished. I thought that was due to “nearest” texture filter. But recently I found out that it was due to something completely different, it’s the side effect of flattenStrong(). Somehow, some overlapping vertices of adjacent letters get welded, or its texcoord loses precission or so, I don’t know exactly. The good news is it’s easy to solve, only by enlarging each letter’s quad to avoid overlapping vertices. See if it’s better.


#9

I can’t seem to get this to run.

Here is the output.

Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Documents and Settings\smartviz>cd Desktop

C:\Documents and Settings\smartviz\Desktop>cd "New Folder"

C:\Documents and Settings\smartviz\Desktop\New Folder>python IDE_STARTER.py
Warning: DirectNotify: category 'Interval' already exists
DirectStart: Starting the game.
:prc(warning): Invalid integer value for ConfigVariable win-size: 600,500
Known pipe types:
  wglGraphicsPipe
(all display modules loaded.)
:prc(warning): Invalid floating-point value for ConfigVariable background-color:
 .1,.1,.1,1
:display:windisplay(warning): Could not find icon filename icon.ico
:display:gsg:glgsg(warning): BlendEquation advertised as supported by OpenGL run
time, but could not get pointers to extension function.
:display:gsg:glgsg(warning): BlendColor advertised as supported by OpenGL runtim
e, but could not get pointers to extension function.
:audio(error):   LoadLibrary() failed, will use NullAudioManager
:audio(error):     Module not found
:util(warning): Adjusting global clock's real time by 5.5873e-006 seconds.
:util(warning): Adjusting global clock's real time by -0.0761046 seconds.
enteringFrame
exitingFrame
enteringFrame
exitingFrame
exitingFrame
########################################
STARTING.....
########################################

C:\Documents and Settings\smartviz\Desktop\New Folder>Warning: DirectNotify: cat
egory 'Interval' already exists
############### YOUR FILES ###############
C:\Documents and Settings\smartviz\Desktop\New Folder\2\dyn1.py
C:\Documents and Settings\smartviz\Desktop\New Folder\2\brokenClass.py
C:\Documents and Settings\smartviz\Desktop\New Folder\2\jackClass.py
C:\Documents and Settings\smartviz\Desktop\New Folder\2\pandaClass.py
C:\Documents and Settings\smartviz\Desktop\New Folder\2\smileyClass.py
##########################################
C:\Documents and Settings\smartviz\Desktop\New Folder\2\dyn1.py
C:\Documents and Settings\smartviz\Desktop\New Folder\2
DirectStart: Starting the game.
Known pipe types:
  wglGraphicsPipe
(all display modules loaded.)
:display:windisplay(warning): Could not find icon filename icon.ico
:display:gsg:glgsg(warning): BlendEquation advertised as supported by openGL run time, but could not get pointers to extension function.
:display:gsg:glgsg(warning): BlendColor advertised as supported by OpenGL runtime, but could not get pointers to extension function.
:audio(error):   LoadLibrary() failed, will use NullAudioManager
:audio(error):     Module not found
:util(warning): Adjusting global clock's real time by 4.74921e-006 seconds.
APP ['WorldInst', '__doc__', '__init__', '__module__', 'moduleName']
APP_modName : dyn1
APP_modName : dyn1
CC_TEMP CLEARED !!
:text(warning): No definition in Lucida Console Regular for character 13
:text(warning): No definition in Lucida Console Regular for character 11
:text(warning): No definition in Lucida Console Regular for character 12
['\x0c', ' ', '$', '(', ',', '0', '4', '8', '<', '@', 'D', 'H', 'L', 'P', 'T', '
X', '\\', '`', 'd', 'h', 'l', 'p', 't', 'x', '|', '\x0b', '#', "'", '+', '/', '3
', '7', ';', '?', 'C', 'G', 'K', 'O', 'S', 'W', '[', '_', 'c', 'g', 'k', 'o', 's
', 'w', '{', '\n', '"', '&', '*', '.', '2', '6', ':', '>', 'B', 'F', 'J', 'N', '
R', 'V', 'Z', '^', 'b', 'f', 'j', 'n', 'r', 'v', 'z', '~', '\t', '\r', '!', '%',
 ')', '-', '1', '5', '9', '=', 'A', 'E', 'I', 'M', 'Q', 'U', 'Y', ']', 'a', 'e',
 'i', 'm', 'q', 'u', 'y', '}']
100
IDE_normal_chars_maxWidth : 0.654545474052
IDE_normal_chars_maxHeight: 2.09090900421
:text(warning): No definition in Lucida Console Regular for character 13
:text(warning): No definition in Lucida Console Regular for character 11
:text(warning): No definition in Lucida Console Regular for character 12
['\x0c', ' ', '$', '(', ',', '0', '4', '8', '<', '@', 'D', 'H', 'L', 'P', 'T', '
X', '\\', '`', 'd', 'h', 'l', 'p', 't', 'x', '|', '\x0b', '#', "'", '+', '/', '3
', '7', ';', '?', 'C', 'G', 'K', 'O', 'S', 'W', '[', '_', 'c', 'g', 'k', 'o', 's
', 'w', '{', '\n', '"', '&', '*', '.', '2', '6', ':', '>', 'B', 'F', 'J', 'N', '
R', 'V', 'Z', '^', 'b', 'f', 'j', 'n', 'r', 'v', 'z', '~', '\t', '\r', '!', '%',
 ')', '-', '1', '5', '9', '=', 'A', 'E', 'I', 'M', 'Q', 'U', 'Y', ']', 'a', 'e',
 'i', 'm', 'q', 'u', 'y', '}']
100
IDE_bold_chars_maxWidth : 0.654545474052
IDE_bold_chars_maxHeight: 2.09090900421
IDE_textScale : Vec3(0.0366667, 1, 0.0366667)
:display(error): Window wouldn't open; abandoning window.
:display:wgldisplay(error): Could not share texture contexts between wglGraphics StateGuardians.

I’m not sure what is going on but the last 2 lines say something I think…

Oh ignore the audio errors the panda version I am using is compiled without FMOD and OpenAL

Robert


#10

I’m not sure either, that’s very weird. Even the Config params are invalid.
The error is very similar to this :
discourse.panda3d.org/viewtopic.php … t=contexts
My own 1.4.2 build works just fine. Perhaps it’s 1.5.0 issue ?
[EDIT]:
I’ll try to replace makeTextureBuffer with makeOutput. I guess you can’t run teapot-on-tv sample too.

I have some (minor) improvements ready for update. I’ll UL it tonight.


#11

I’ve used makeOutput, but still using different framebuffer properties. It might not work. I tried to use main window’s FBprops but the RTT result was funny, so I dropped it.

UPDATE :

  1. changed keys for moving line(s) and duplicating line. Instead of using modifier keys (Shift-Ctrl-Alt), now I use double Ctrl, so I only need to utilize 1 hand. Double Ctrl press threshold is .3 second.
  2. pausing the scene now correctly pauses all scene’s intervals and tasks (both oridinary and doLater tasks).
  3. upon rebind, all doLater tasks get removed to avoid unnecessary annoying assertion error due to operating on no-longer-exist objects.
  4. code completion : works a little more correct on imported stuff, temporarily imported upon module/document switch (or anytime a document is set to active). Class instance attributes now includes all of its methods, but still not properly usable yet.
  5. added destructor for sound

#12

UPDATE :

  1. the last edited files list now always saved upon exit, and can be loaded in the next execution.
  2. integrated WxPython, mainly to replace the limited my own file dialog and create a welcome screen. Luckily, it also allows me to use a better IDE-OS clipboards management and interaction. It’s my 1st time using this cool serves-everything GUI lib, so there should be better ways in doing things.
  3. moved the IDE’s root to render2dp, to avoid it being affected by user’s need over render2d and aspect2d.
  4. added pools clears for models, textures, and shaders
  5. added destructors for collision traverser and handlerPhysical
  6. added collisions in the sample scene
    [EDIT 05/22/08]:
  7. any camera is preserved upon update

more shots :


#13

Ok, still doesn’t run :frowning:

A few things…

may have to do with the WXPython version…

I downloaded: http://downloads.sourceforge.net/sourceforge/wxpython/wxPython2.6-win32-unicode-2.6.4.0-py25.exe

Firstly, when I clicked open / new There was an error saying that

Traceback (most recent call last):
  File "IDE_STARTER.pyw", line 265, in __init__
    self.SetTransparent(ALPHA_optionsScreen)
AttributeError: 'CreateNewFile' object has no attribute 'SetTransparent'

So I commented out these 2 lines

193 #self.SetTransparent(ALPHA_optionsScreen)
265 #self.SetTransparent(ALPHA_optionsScreen)

Then this error was raised after creating a new file.

PREVIEW UPDATED
Nothing was selected.
########################################
STARTING.....
########################################

C:\Documents and Settings\smartviz\Desktop\asdf>Warning: DirectNotify: category
'Interval' already exists
############### YOUR FILES ###############
C:\Documents and Settings\smartviz\Desktop\asdf\brt.py
##########################################
DirectStart: Starting the game.
Known pipe types:
  wglGraphicsPipe
(all display modules loaded.)
:display:windisplay(warning): Could not find icon filename icon.ico
:display:gsg:glgsg(warning): BlendEquation advertised as supported by OpenGL run
time, but could not get pointers to extension function.
:display:gsg:glgsg(warning): BlendColor advertised as supported by OpenGL runtim
e, but could not get pointers to extension function.
:audio(error):   LoadLibrary() failed, will use NullAudioManager
:audio(error):     Module not found
:util(warning): Adjusting global clock's real time by 8.66315e-006 seconds.
APP ['WorldInst', '__doc__', '__init__', '__module__', 'modDir', 'moduleName']
APP_modName : brt
APP_modName : brt
CC_TEMP CLEARED !!
Traceback (most recent call last):
  File "IDE.py", line 449, in <module>
    base.startWx()
AttributeError: ShowBase instance has no attribute 'startWx'
>>>

Again looks like the wxpython playing up, where / how did you install your wxpython / what os are you using?

Robert.


#14

Why are you still using v.2.6 ? Here I use wx v2.8, the latest, and Panda 1.5.1. I don’t know since which version startWx was added to ShowBase.

self.SetTransparent :
self is CreateNewFile instance, derived from wx.Frame, so it’s a method of a wx.Frame.

It was developed on Windows. But I have just setup a Hardy box (I’m a 3 days linuxer :smiley:) with the latest NVIDIA driver, and I have Panda’s gutsy .deb v1.5.2, I’ll try it soon on Hardy.

rninne, what’s your graphics card ?
For the previous RTT problem you have, do the render-to-texture samples work ?
RTT setup is tricky, the result varies too much across graphics cards.


#15

Well I chose v.2.6 because it said latest stable release :stuck_out_tongue: Ill try with v2.8

Welcome to Linux! I’m glad that you chose Ubuntu.

It is a Colorgraphic Xentera GT… dxdiag tells me it has 4 ATI mobility radeon 9000’s (shaders aren’t supported on this card… but I’m sure it is the drivers, since it is a specialist card and Colorgraphic have stopped supporting it it’s hard to get updates)

With regards to that I’ll try it on my other computer it has a more standard card (NVIDIA 7600 GS).

Robert.


#16

Well, life must go on, and v2.6 is just too old.
You’d be better stick to your 7600 GS.

[EDIT]:
for the base.startWx, you can use the next lines (for creating the wx.App instance and the loop) in IDE.py instead of it.


#17

I am currently trying to port the app to os x. While doing this i wanted to post one mayor problem of wxpython (under osx):

if using StaticBoxSizer, all objects that are added must be created after the StaticBoxSizer.

this:

WELCOME_openLastEditedFilesBtn = wx.Button(welcomeScreenPanel, -1, 'Open Last Edited Files',size=(0,50))
if os.path.exists('lastFiles') and os.stat('lastFiles')[6]>0:
   WELCOME_openLastEditedFilesBtn.Bind(wx.EVT_BUTTON,OpenLastEditedFiles)
else:
   WELCOME_openLastEditedFilesBtn.Disable()

WELCOME_openFilesBtn = wx.Button(welcomeScreenPanel, -1, 'Open Files',size=(0,50))
WELCOME_openFilesBtn.Bind(wx.EVT_BUTTON,OpenFiles)

WELCOME_createNewFileBtn = wx.Button(welcomeScreenPanel, -1, 'Create New File',size=(0,50))
WELCOME_createNewFileBtn.Bind(wx.EVT_BUTTON,CreateNewFile)

WELCOME_buttonsSizer = wx.StaticBoxSizer(wx.StaticBox(welcomeScreenPanel),wx.VERTICAL)
WELCOME_buttonsSizer.Add((250,0))
WELCOME_buttonsSizer.Add(WELCOME_openLastEditedFilesBtn, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL, 5)
WELCOME_buttonsSizer.Add(WELCOME_openFilesBtn, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL, 5)
WELCOME_buttonsSizer.Add(WELCOME_createNewFileBtn, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL, 5)

must be changed to this:

WELCOME_buttonsSizer = wx.StaticBoxSizer(wx.StaticBox(welcomeScreenPanel),wx.VERTICAL)

WELCOME_openLastEditedFilesBtn = wx.Button(welcomeScreenPanel, -1, 'Open Last Edited Files',size=(0,50))
if os.path.exists('lastFiles') and os.stat('lastFiles')[6]>0:
   WELCOME_openLastEditedFilesBtn.Bind(wx.EVT_BUTTON,OpenLastEditedFiles)
else:
   WELCOME_openLastEditedFilesBtn.Disable()

WELCOME_openFilesBtn = wx.Button(welcomeScreenPanel, -1, 'Open Files',size=(0,50))
WELCOME_openFilesBtn.Bind(wx.EVT_BUTTON,OpenFiles)

WELCOME_createNewFileBtn = wx.Button(welcomeScreenPanel, -1, 'Create New File',size=(0,50))
WELCOME_createNewFileBtn.Bind(wx.EVT_BUTTON,CreateNewFile)

WELCOME_buttonsSizer.Add((250,0))
WELCOME_buttonsSizer.Add(WELCOME_openLastEditedFilesBtn, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL, 5)
WELCOME_buttonsSizer.Add(WELCOME_openFilesBtn, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL, 5)
WELCOME_buttonsSizer.Add(WELCOME_createNewFileBtn, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL, 5)

it would be great, if you could consider this, while you continue your work.


#18

Great shot, Hypnos !
So, I guess the StaticBox doesn’t wrap all children defined before the StaticBoxSizer is created. Is that it ? How about BoxSizer, is it buggy too ?
Are there anything else I should be aware of ?


#19

I got it mostly working in the meantime, i dont think anything else is affected. I could open files and start the ide (i have not checked if the BoxSizer is used in those parts).

I didnt really understand why StaticBoxSizer is not working correctly. It took me a while to figure out this solution from the messages i found on the internet. But it seems to be a known osx problem for wx-windows.


Another problem i have found, under osx is that os.execl does not work while using wx-windows. A possibility is to keep the window opened (by using os.spawnl)

    if sys.platform == "darwin":
        pythonExecutable = "/usr/bin/python" # i think thats the usual py2.5 from 10.5 (leopard)
        result = os.spawnlp( os.P_NOWAIT, pythonExecutable,' -i ', the_IDE, the_files, ' %i'%PStatsEnabled)
    else:
        os.execl(sys.executable.replace('pythonw','ppython'),' -i ',the_IDE,the_files,' %i'%PStatsEnabled)

I think adding sys.path.append(’.’) to IDE.py will fix a problem which can occur in APP_MODULE when importing modules from the loaded file. I think the path is somehow not set correctly when spawning the ide process.


Maybe a working directory should be defined when loading a file.
i sometimes use a filestructure like this:

- panda_function_lib_dir
  - __init__.py
  - file1.py
  - file2.py
- currect_project_dir
  - main.py
  - class2.py

Where main contains:

from panda_function_lib_dir import file1

This does not work with the current structure.


The APP_files is a list of ‘"/path/to/file"’, the filename should be stripped of "

APP_files_unstrip=sys.argv[1].split('::::')
APP_files = list()
for app in APP_files_unstrip:
    APP_files.append( app.strip('"') )

I have changed a lot of other things, but most of them related to the fact that i still use python 2.4 ("var = ‘x’ if a else ‘y’ does not exist in 2.4)


#20

Sorry, it took me too long. My first 1.5.2 .deb was corrupt, so I had to DL it again, plus wxPython was not installed by default in Hardy 8.0.4, so I had to install GTK+2 and build wxWidgets myself. Got confused a bit, I did some parts of the build process a little differently and got stuck for a while. :S
After it was built, I moved wx’s /lib/* to /usr/lib and the built /wx to python2.5/site-packages. The demo works gorgeously, but when I tried the IDE, none of the threads work. I use new thread to display all dialog (except 1, the exit & save confirmation), since ShowModal never return. On Windows, that works fine, but not on Linux.
Any clue about that ? Could it be something wrong with my wx build ? Perhaps I missed something.

Other bad news on Linux :
[x] The code-completion description’s RTT is at low res
[x] the sort order of 2d nodes get scrambled
Perhaps they’re simply P3D version changes (serious !) issues, I use 1.5.1 on Windows, and 1.5.2 on Linux.
[x] wx’s clipboard must be checked if it’s already opened, otherwise assertion error !
[x] wx show event for the code preview panel in create-new-file step doesn’t fired at all, causes the preview never generated at all
I’ll take closer look at them soon.

Good news :

I have re-arranged all StaticBoxSizers.


Before migrated to execl recently, I’ve used to use spawnl P_NOWAIT, plus sys.exit.
The only reason is, on Windows, most of the time, using spawnl minimizes the python console, it’s kinda annoying. One thing you (might) miss was closing the welcome screen window (sys.exit after os.spawnl). I could be wrong, so what’s the difference of with and without sys.exit ? The problem is solved as soon as the new python session is spawned, isn’t it ?


In IDE.py, I already inserted the main script’s dir to the path :

IDE_lastBrowsePath=os.path.dirname(APP_mainFile)
sys.path.insert(0,IDE_lastBrowsePath)

at the beginning, before importing user’s app, and nothing went wrong on Linux. Moreover, I always stick to /root when running “python /path/to/IDE_STARTER.pyw” on terminal.


On Windows, I used to execute “python script.py” not from console, so the CWD is set automatically to script’s dir. But on Linux (so far I always start the IDE from terminal, still from /root), so the CWD isn’t changed.
I just added this to IDE_STARTER, so the panda image can be found :

# sets the working dir to the script's location, just to ease the pain
os.chdir( os.path.dirname(sys.argv[0]) )

but I haven’t tried adding that in IDE.py though.


On Windows it’s without double-quotes, since double-quotes are automatically stripped by the OS. I guess Unix uses single-quotes, isn’t it ?
Actually, sys.argv[1] is “/path/to/file1::::/path/to/file2::::/path/to/file3”, not “/path/to/file1”::::"/path/to/file2"::::"/path/to/file3", so this works :

APP_files=sys.argv[1].strip('"').split('::::')

Thanks for your attention, Hypnos !
BTW, is there any delicious reason to stick to python 2.4 ? v2.5 offers some performance optimizations and more interesting things.


#21

Uhrm, shouldn’t that be more something along the lines of:

APP_files=sys.argv[1].split('::::').strip('"')

Small typo? :slight_smile:


#22

actually APP_files=sys.argv[1].strip(’"’).split(’::::’) would make sense, if it’s only 1 file (where the split would not be used)

but APP_files=sys.argv[1].split(’::::’).strip(’"’) does not work, because a list cant be stripped.

maybe some re is what we need?
or:

APP_files=sys.argv[1].strip('"').split('"::::"')

but this needs to be checked for platform type (as it seems to differ for osx & windows and maybe linux).


#23

Don’t worry about it, guys. It’s not a problem at all.
I don’t think there is any OS allows these characters to be part of a filename : "*?/:<>|
Those paths are definitely free of quotes. The quotes serve only to pack the ::::-concat’ed paths, here in IDE_STARTER.startIDE :

the_files='"%s"'%'::::'.join(files)

It’s only to asure that all paths, which may contain whitespaces are properly packed as a single argument to python. If I leave this string passed over as is, it would be split to be some arguments :
/I am/pathTo/file 1.py::::/I am/pathTo/file 2.py::::/I am/pathTo/file 3.py
The quotes are just a packer :
“/I am/pathTo/file 1.py::::/I am/pathTo/file 2.py::::/I am/pathTo/file 3.py”
So, to extract the paths, first I have to strip those quotes, then split the result by ::::. I’ve tried that both on Windows and Linux, nothing is wrong. I don’t know about OS X’s packer though, I think quotes (both single and double) are universal.

If you guys want to worry, there is 1 more bad news :confused:
[x] on Windows, wx can store & retrieve clipboard text content without any problem, though I have to close it using Flush() to actually store it, so it’s available to the OS, since Close() doesn’t seem enough. Unfortunately, not even Flush() work on Linux, I don’t know why.
I thought that all those problems were caused by my a little dirty build. I have just done a clean build, but it still behaves the same. There must be something wrong somewhere else…
It could be me being so new to Linux…

[+] I’ve fixed the cross platforms EOL-delimiter. File loading now uses universal newline character read mode : ‘rU’.