Kivy-examples 2.3.1.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/3Drendering/main.py +77 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/3Drendering/monkey.obj +7966 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/3Drendering/objloader.py +147 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/3Drendering/simple.glsl +47 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/RST_Editor/editor.kv +72 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/RST_Editor/main.py +64 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/android/compass/android.txt +3 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/android/compass/compass.kv +25 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/android/compass/main.py +77 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/android/compass/needle.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/android/compass/rose.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/android/takepicture/android.txt +3 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/android/takepicture/main.py +80 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/android/takepicture/shadow32.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/android/takepicture/takepicture.kv +40 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/animation/animate.py +42 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/application/app_suite.py +152 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/application/app_suite_data/testkvdir.kv +4 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/application/app_with_build.py +24 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/application/app_with_config.py +49 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/application/app_with_kv.py +25 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/application/app_with_kv_in_template1.py +27 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/application/template1/test.kv +4 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/application/test.kv +4 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/application/testkvfile.kv +4 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/async/asyncio_advanced.py +90 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/async/asyncio_basic.py +59 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/async/trio_advanced.py +93 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/async/trio_basic.py +58 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12908_sweet_trip_mm_clap_hi.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12909_sweet_trip_mm_clap_lo.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12910_sweet_trip_mm_clap_mid.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12911_sweet_trip_mm_hat_cl.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12913_sweet_trip_mm_kick_hi.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12914_sweet_trip_mm_kick_lo.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12915_sweet_trip_mm_kick_mid.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12916_sweet_trip_mm_kwik_mod_01.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12917_sweet_trip_mm_kwik_mod_02.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12918_sweet_trip_mm_kwik_mod_03.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12919_sweet_trip_mm_kwik_mod_04.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12920_sweet_trip_mm_kwik_mod_05.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12921_sweet_trip_mm_kwik_mod_06.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12922_sweet_trip_mm_kwik_mod_07.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12923_sweet_trip_mm_metal_clave.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12925_sweet_trip_mm_sweep_x.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12926_sweet_trip_mm_sweep_y.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/12927_sweet_trip_mm_sweep_z.wav +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/audio.kv +59 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/main.py +81 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/audio/pitch.py +42 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/camera/main.py +59 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/bezier.py +105 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/canvas_stress.py +72 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/circle.py +84 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/fbo_canvas.py +91 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/kiwi.jpg +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/lines.py +296 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/lines_extended.py +183 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/mesh.py +57 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/mesh_manipulation.py +101 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/mtexture1.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/mtexture2.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/multitexture.py +110 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/repeat_texture.py +65 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/rotation.py +35 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/rounded_rectangle.py +153 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/scale.py +37 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/stencil_canvas.py +85 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/tesselate.py +146 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/texture.py +143 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/canvas/texture_example_image.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/container/kv/1.kv +28 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/container/kv/2.kv +28 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/container/kv/3.kv +28 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/container/kv/root.kv +32 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/container/main.py +63 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/cover/cover_image.py +25 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/cover/cover_video.py +31 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/camera_puzzle.py +98 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/AnchorLayoutContainer.kv +15 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/BoxLayoutContainer.kv +14 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/ButtonContainer.kv +27 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/CheckBoxContainer.kv +28 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/FileChooserContainer.kv +19 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/FloatLayoutContainer.kv +16 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/GridLayoutContainer.kv +20 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/LabelContainer.kv +62 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/MediaContainer.kv +9 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/PlaygroundContainer.kv +4 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/PopupContainer.kv +39 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/ProgressBarContainer.kv +17 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/RestContainer.kv +5 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/ScatterContainer.kv +16 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/SelectorsContainer.kv +10 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/StackLayoutContainer.kv +25 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/container_kvs/TextContainer.kv +20 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/kivycatalog.kv +144 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/kivycatalog/main.py +192 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/multistroke/gesturedatabase.kv +117 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/multistroke/gesturedatabase.py +180 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/multistroke/helpers.py +30 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/multistroke/historymanager.kv +164 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/multistroke/historymanager.py +276 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/multistroke/main.py +144 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/multistroke/multistroke.kv +101 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/multistroke/settings.kv +110 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/multistroke/settings.py +97 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/pictures/android.txt +3 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/pictures/images/Bubbles.jpg +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/pictures/images/Ill1.jpg +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/pictures/images/Wall.jpg +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/pictures/images/faust_github.jpg +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/pictures/main.py +73 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/pictures/pictures.kv +57 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/pictures/shadow32.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/shadereditor/main.py +147 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/shadereditor/shadereditor.kv +39 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/README.txt +11 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/android.txt +3 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/background.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/faust_github.jpg +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/icons/README +4 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/icons/bug.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/icons/chevron-left.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/icons/chevron-right.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/accordions.kv +39 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/bubbles.kv +33 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/buttons.kv +26 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/carousel.kv +51 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/checkboxes.kv +33 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/codeinput.kv +9 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/dropdown.kv +40 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/filechoosers.kv +24 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/popups.kv +17 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/progressbar.kv +15 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/rstdocument.kv +24 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/scatter.kv +14 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/screenmanager.kv +46 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/sliders.kv +55 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/spinner.kv +11 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/splitter.kv +13 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/switches.kv +39 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/tabbedpanel + layouts.kv +69 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/textinputs.kv +48 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/data/screens/togglebutton.kv +39 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/main.py +243 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/showcase/showcase.kv +100 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/touchtracer/README.txt +12 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/touchtracer/android.txt +3 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/touchtracer/icon.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/touchtracer/main.py +170 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/touchtracer/particle.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/demo/touchtracer/touchtracer.kv +29 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/frameworks/twisted/echo_client_app.py +82 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/frameworks/twisted/echo_server_app.py +49 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/frameworks/twisted/twistd_app.py +66 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/gestures/gesture_board.py +95 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/gestures/my_gestures.py +90 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/guide/designwithkv/controller.kv +16 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/guide/designwithkv/main.py +29 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/guide/firstwidget/1_skeleton.py +15 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/guide/firstwidget/2_print_touch.py +16 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/guide/firstwidget/3_draw_ellipse.py +22 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/guide/firstwidget/4_draw_line.py +26 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/guide/firstwidget/5_random_colors.py +28 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/guide/firstwidget/6_button.py +38 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/guide/quickstart/main.py +15 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/includes/button.kv +9 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/includes/layout.kv +6 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/includes/main.py +19 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/includes/test.kv +5 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/keyboard/android.txt +3 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/keyboard/main.py +226 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/keyboard/numeric.json +38 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kinect/README.txt +13 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kinect/kinectviewer.py +283 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/app_button.kv +9 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/app_camera.kv +25 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/app_fbo.kv +11 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/app_layout.kv +23 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/app_logo.kv +36 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/app_scatter.kv +6 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/app_stencil.kv +27 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/app_video.kv +42 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/builder_template.py +28 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/ids/id_in_kv/id_in_kv.py +20 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/ids/id_in_kv/test.kv +11 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/ids/kv_and_py/kv_and_py.py +34 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/ids/kv_and_py/test.kv +11 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/kivy.jpg +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/kv/kvrun.py +38 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/clipboard.py +63 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/custom_titlebar.py +56 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/imagesave.py +14 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/joystick.py +83 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/multiple_dropfile.py +51 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/on_textedit_event.py +104 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/opacitywindow.py +28 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/shapecollisions.py +397 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/shapedwindow.py +98 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/two_panes.py +47 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/miscellaneous/urlrequest.py +128 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/settings/android.txt +3 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/settings/main.py +122 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/shader/plasma.kv +9 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/shader/plasma.py +86 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/shader/rotated.kv +91 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/shader/rotated.py +102 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/shader/shadertree.kv +29 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/shader/shadertree.py +193 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/shader/tex3.jpg +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/svg/benchmark.py +19 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/svg/cloud.svg +25 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/svg/main-smaa.py +155 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/svg/main.py +50 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/svg/music.svg +68 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/svg/rotated.svg +23 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/svg/ship.svg +181 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/svg/sun.svg +35 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/svg/tiger.svg +813 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/text/pango_demo.py +296 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/notes/final/data/icon.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/notes/final/main.py +163 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/notes/final/note.kv +154 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/main.py +82 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/pong.kv +53 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/steps/step1/main.py +15 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/steps/step1/pong.kv +2 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/steps/step2/main.py +15 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/steps/step2/pong.kv +21 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/steps/step3/main.py +26 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/steps/step3/pong.kv +31 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/steps/step4/main.py +48 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/steps/step4/pong.kv +34 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/steps/step5/main.py +75 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/tutorials/pong/steps/step5/pong.kv +53 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/accordion_1.py +17 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/actionbar.py +32 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/asyncimage.py +35 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/boxlayout_poshint.py +54 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/bubble_test.py +63 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/camera.py +33 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/carousel_buttons.py +50 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/cityCC0.mpg +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/cityCC0.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/codeinput.py +225 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/codeinputtest.kv +53 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/colorpicker.py +234 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/colorusage.py +62 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/compound_selection.py +83 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/customcollide.py +82 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/effectwidget.py +193 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/effectwidget2.py +47 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/effectwidget3_advanced.py +62 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/fbowidget.py +111 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/focus_behavior.py +98 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/image_mipmap.py +31 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/keyboardlistener.py +42 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/label_mipmap.py +28 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/label_sizing.py +193 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/label_text_size.py +49 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/label_with_markup.py +21 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/lang_dynamic_classes.py +18 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/pagelayout.py +64 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/popup_with_kv.py +35 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/recycleview/basic_data.py +124 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/recycleview/infinite_scrolling.py +143 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/recycleview/key_viewclass.py +149 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/recycleview/messenger.py +196 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/recycleview/pull_to_refresh.py +95 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/recycleview/rv_animate_items.py +109 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/rstexample.py +128 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/scatter.kv +53 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/scatter.py +16 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/screenmanager.py +106 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/scrollview.kv +16 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/scrollview.py +40 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/android.txt +3 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/data/images/bird.zip +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/data/images/button_white.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/data/images/button_white_animated.zip +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/data/images/cube.zip +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/data/images/info.png +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/data/images/info.zip +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/data/images/simple_cv_joint_animated.gif +0 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/main.kv +63 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/main.py +150 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/uix/__init__.py +7 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/sequenced_images/uix/custom_button.py +98 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/settings.py +93 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/shorten_text.py +80 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/spinner.py +17 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/splitter.py +74 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/tabbed_panel_showcase.py +316 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/tabbedpanel.py +50 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/textalign.kv +49 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/textalign.py +48 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/textinput.py +59 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/unicode_textinput.py +244 -0
- Kivy_examples-2.3.1.dev0.data/data/share/kivy-examples/widgets/videoplayer.py +26 -0
- Kivy_examples-2.3.1.dev0.dist-info/AUTHORS +66 -0
- Kivy_examples-2.3.1.dev0.dist-info/LICENSE +21 -0
- Kivy_examples-2.3.1.dev0.dist-info/METADATA +382 -0
- Kivy_examples-2.3.1.dev0.dist-info/RECORD +624 -0
- Kivy_examples-2.3.1.dev0.dist-info/WHEEL +5 -0
- Kivy_examples-2.3.1.dev0.dist-info/dependency_links.txt +1 -0
- Kivy_examples-2.3.1.dev0.dist-info/top_level.txt +1 -0
- kivy/__init__.py +519 -0
- kivy/_version.py +18 -0
- kivy/animation.py +831 -0
- kivy/app.py +1213 -0
- kivy/atlas.py +456 -0
- kivy/base.py +617 -0
- kivy/cache.py +262 -0
- kivy/clock.py +1172 -0
- kivy/compat.py +82 -0
- kivy/config.py +1004 -0
- kivy/context.py +102 -0
- kivy/core/__init__.py +247 -0
- kivy/core/audio/__init__.py +223 -0
- kivy/core/audio/audio_android.py +104 -0
- kivy/core/audio/audio_avplayer.py +82 -0
- kivy/core/audio/audio_ffpyplayer.py +185 -0
- kivy/core/audio/audio_gstplayer.py +101 -0
- kivy/core/audio/audio_pygame.py +127 -0
- kivy/core/camera/__init__.py +151 -0
- kivy/core/camera/camera_android.py +206 -0
- kivy/core/camera/camera_gi.py +170 -0
- kivy/core/camera/camera_opencv.py +163 -0
- kivy/core/camera/camera_picamera.py +96 -0
- kivy/core/clipboard/__init__.py +157 -0
- kivy/core/clipboard/_clipboard_ext.py +36 -0
- kivy/core/clipboard/clipboard_android.py +91 -0
- kivy/core/clipboard/clipboard_dbusklipper.py +41 -0
- kivy/core/clipboard/clipboard_dummy.py +26 -0
- kivy/core/clipboard/clipboard_gtk3.py +47 -0
- kivy/core/clipboard/clipboard_nspaste.py +44 -0
- kivy/core/clipboard/clipboard_pygame.py +67 -0
- kivy/core/clipboard/clipboard_sdl2.py +36 -0
- kivy/core/clipboard/clipboard_winctypes.py +107 -0
- kivy/core/clipboard/clipboard_xclip.py +29 -0
- kivy/core/clipboard/clipboard_xsel.py +26 -0
- kivy/core/gl/__init__.py +90 -0
- kivy/core/image/__init__.py +996 -0
- kivy/core/image/img_dds.py +40 -0
- kivy/core/image/img_ffpyplayer.py +87 -0
- kivy/core/image/img_pil.py +123 -0
- kivy/core/image/img_pygame.py +119 -0
- kivy/core/image/img_sdl2.py +66 -0
- kivy/core/image/img_tex.py +58 -0
- kivy/core/spelling/__init__.py +135 -0
- kivy/core/spelling/spelling_enchant.py +50 -0
- kivy/core/spelling/spelling_osxappkit.py +64 -0
- kivy/core/text/__init__.py +1090 -0
- kivy/core/text/markup.py +893 -0
- kivy/core/text/text_pango.py +145 -0
- kivy/core/text/text_pil.py +84 -0
- kivy/core/text/text_pygame.py +117 -0
- kivy/core/text/text_sdl2.py +50 -0
- kivy/core/video/__init__.py +219 -0
- kivy/core/video/video_ffmpeg.py +106 -0
- kivy/core/video/video_ffpyplayer.py +449 -0
- kivy/core/video/video_gstplayer.py +140 -0
- kivy/core/video/video_null.py +12 -0
- kivy/core/window/__init__.py +2515 -0
- kivy/core/window/window_egl_rpi.py +86 -0
- kivy/core/window/window_pygame.py +441 -0
- kivy/core/window/window_sdl2.py +999 -0
- kivy/deps/__init__.py +6 -0
- kivy/effects/__init__.py +23 -0
- kivy/effects/dampedscroll.py +114 -0
- kivy/effects/kinetic.py +193 -0
- kivy/effects/opacityscroll.py +27 -0
- kivy/effects/scroll.py +126 -0
- kivy/event.py +12 -0
- kivy/eventmanager/__init__.py +185 -0
- kivy/extras/__init__.py +0 -0
- kivy/extras/highlight.py +52 -0
- kivy/factory.py +190 -0
- kivy/factory_registers.py +201 -0
- kivy/garden/__init__.py +186 -0
- kivy/geometry.py +121 -0
- kivy/gesture.py +424 -0
- kivy/graphics/__init__.py +126 -0
- kivy/graphics/cgl_backend/__init__.py +0 -0
- kivy/input/__init__.py +39 -0
- kivy/input/factory.py +35 -0
- kivy/input/motionevent.py +587 -0
- kivy/input/postproc/__init__.py +27 -0
- kivy/input/postproc/calibration.py +200 -0
- kivy/input/postproc/dejitter.py +74 -0
- kivy/input/postproc/doubletap.py +101 -0
- kivy/input/postproc/ignorelist.py +47 -0
- kivy/input/postproc/retaintouch.py +93 -0
- kivy/input/postproc/tripletap.py +106 -0
- kivy/input/provider.py +40 -0
- kivy/input/providers/__init__.py +68 -0
- kivy/input/providers/androidjoystick.py +117 -0
- kivy/input/providers/hidinput.py +778 -0
- kivy/input/providers/leapfinger.py +113 -0
- kivy/input/providers/linuxwacom.py +396 -0
- kivy/input/providers/mactouch.py +220 -0
- kivy/input/providers/mouse.py +424 -0
- kivy/input/providers/mtdev.py +380 -0
- kivy/input/providers/probesysfs.py +254 -0
- kivy/input/providers/tuio.py +326 -0
- kivy/input/providers/wm_common.py +162 -0
- kivy/input/providers/wm_pen.py +121 -0
- kivy/input/providers/wm_touch.py +157 -0
- kivy/input/recorder.py +335 -0
- kivy/input/shape.py +27 -0
- kivy/interactive.py +335 -0
- kivy/lang/__init__.py +883 -0
- kivy/lang/builder.py +1004 -0
- kivy/lang/parser.py +822 -0
- kivy/lib/__init__.py +21 -0
- kivy/lib/ddsfile.py +419 -0
- kivy/lib/gstplayer/__init__.py +27 -0
- kivy/lib/mtdev.py +254 -0
- kivy/lib/vidcore_lite/__init__.py +0 -0
- kivy/loader.py +579 -0
- kivy/logger.py +646 -0
- kivy/metrics.py +421 -0
- kivy/modules/__init__.py +300 -0
- kivy/modules/_webdebugger.py +200 -0
- kivy/modules/console.py +1059 -0
- kivy/modules/cursor.py +75 -0
- kivy/modules/inspector.py +755 -0
- kivy/modules/joycursor.py +299 -0
- kivy/modules/keybinding.py +64 -0
- kivy/modules/monitor.py +90 -0
- kivy/modules/recorder.py +94 -0
- kivy/modules/screen.py +183 -0
- kivy/modules/showborder.py +33 -0
- kivy/modules/touchring.py +97 -0
- kivy/modules/webdebugger.py +30 -0
- kivy/multistroke.py +1477 -0
- kivy/network/__init__.py +7 -0
- kivy/network/urlrequest.py +794 -0
- kivy/parser.py +154 -0
- kivy/resources.py +102 -0
- kivy/storage/__init__.py +405 -0
- kivy/storage/dictstore.py +98 -0
- kivy/storage/jsonstore.py +92 -0
- kivy/storage/redisstore.py +103 -0
- kivy/support.py +267 -0
- kivy/tests/__init__.py +11 -0
- kivy/tests/async_common.py +568 -0
- kivy/tests/common.py +524 -0
- kivy/tests/conftest.py +33 -0
- kivy/tests/fixtures.py +169 -0
- kivy/tests/perf_test_textinput.py +195 -0
- kivy/tests/pyinstaller/simple_widget/main.py +12 -0
- kivy/tests/pyinstaller/simple_widget/project/__init__.py +0 -0
- kivy/tests/pyinstaller/simple_widget/project/widget.py +12 -0
- kivy/tests/pyinstaller/test_pyinstaller.py +115 -0
- kivy/tests/pyinstaller/video_widget/main.py +6 -0
- kivy/tests/pyinstaller/video_widget/project/__init__.py +38 -0
- kivy/tests/test_animations.py +415 -0
- kivy/tests/test_app.py +216 -0
- kivy/tests/test_audio.py +69 -0
- kivy/tests/test_benchmark.py +292 -0
- kivy/tests/test_clipboard.py +48 -0
- kivy/tests/test_clock.py +292 -0
- kivy/tests/test_compat.py +6 -0
- kivy/tests/test_config.py +35 -0
- kivy/tests/test_coverage.py +83 -0
- kivy/tests/test_doc_gallery.py +38 -0
- kivy/tests/test_environ_cli.py +50 -0
- kivy/tests/test_fbo_py2py3.py +74 -0
- kivy/tests/test_filechooser.py +11 -0
- kivy/tests/test_filechooser_unicode.py +82 -0
- kivy/tests/test_fonts.py +42 -0
- kivy/tests/test_garden.py +23 -0
- kivy/tests/test_graphics.py +1149 -0
- kivy/tests/test_graphics_svg.py +84 -0
- kivy/tests/test_image.py +74 -0
- kivy/tests/test_imageloader.py +485 -0
- kivy/tests/test_invalid_lang.py +42 -0
- kivy/tests/test_issues/test_6315.py +55 -0
- kivy/tests/test_issues/test_issue_1084.py +47 -0
- kivy/tests/test_issues/test_issue_1091.py +19 -0
- kivy/tests/test_issues/test_issue_599.py +21 -0
- kivy/tests/test_issues/test_issue_609.py +19 -0
- kivy/tests/test_issues/test_issue_6909.py +28 -0
- kivy/tests/test_issues/test_issue_883.py +12 -0
- kivy/tests/test_kivy_init.py +30 -0
- kivy/tests/test_knspace.py +247 -0
- kivy/tests/test_lang.py +431 -0
- kivy/tests/test_lang_complex.py +87 -0
- kivy/tests/test_lang_pre_process_and_post_process.py +394 -0
- kivy/tests/test_logger.py +516 -0
- kivy/tests/test_metrics.py +30 -0
- kivy/tests/test_module_inspector.py +382 -0
- kivy/tests/test_motion_event.py +44 -0
- kivy/tests/test_mouse_hover_event.py +249 -0
- kivy/tests/test_mouse_multitouchsim.py +554 -0
- kivy/tests/test_multistroke.py +389 -0
- kivy/tests/test_properties.py +1332 -0
- kivy/tests/test_resources.py +79 -0
- kivy/tests/test_rst_replace.py +63 -0
- kivy/tests/test_screen.py +38 -0
- kivy/tests/test_storage.py +135 -0
- kivy/tests/test_uix_actionbar.py +363 -0
- kivy/tests/test_uix_anchorlayout.py +79 -0
- kivy/tests/test_uix_asyncimage.py +133 -0
- kivy/tests/test_uix_boxlayout.py +94 -0
- kivy/tests/test_uix_bubble.py +425 -0
- kivy/tests/test_uix_carousel.py +93 -0
- kivy/tests/test_uix_colorpicker.py +77 -0
- kivy/tests/test_uix_dropdown.py +91 -0
- kivy/tests/test_uix_gridlayout.py +244 -0
- kivy/tests/test_uix_layout.py +16 -0
- kivy/tests/test_uix_modal.py +101 -0
- kivy/tests/test_uix_recyclegridlayout.py +383 -0
- kivy/tests/test_uix_relativelayout.py +30 -0
- kivy/tests/test_uix_scrollview.py +358 -0
- kivy/tests/test_uix_settings.py +33 -0
- kivy/tests/test_uix_slider.py +156 -0
- kivy/tests/test_uix_stacklayout.py +120 -0
- kivy/tests/test_uix_textinput.py +577 -0
- kivy/tests/test_uix_translate_coordinates.py +72 -0
- kivy/tests/test_uix_videoplayer.py +112 -0
- kivy/tests/test_uix_widget.py +137 -0
- kivy/tests/test_urlrequest/test_urlrequest_requests.py +378 -0
- kivy/tests/test_urlrequest/test_urlrequest_urllib.py +155 -0
- kivy/tests/test_utils.py +237 -0
- kivy/tests/test_vector.py +256 -0
- kivy/tests/test_video.py +25 -0
- kivy/tests/test_weakmethod.py +44 -0
- kivy/tests/test_widget.py +127 -0
- kivy/tests/test_widget_walk.py +70 -0
- kivy/tests/test_window_base.py +60 -0
- kivy/tests/test_window_info.py +29 -0
- kivy/tests/visual_test_label.py +291 -0
- kivy/tools/__init__.py +44 -0
- kivy/tools/benchmark.py +286 -0
- kivy/tools/changelog_parser.py +120 -0
- kivy/tools/coverage.py +135 -0
- kivy/tools/gallery.py +323 -0
- kivy/tools/generate-icons.py +117 -0
- kivy/tools/gles_compat/subset_gles.py +125 -0
- kivy/tools/highlight/__init__.py +9 -0
- kivy/tools/kviewer.py +80 -0
- kivy/tools/packaging/__init__.py +12 -0
- kivy/tools/packaging/cython_cfg.py +82 -0
- kivy/tools/packaging/factory.py +105 -0
- kivy/tools/packaging/pyinstaller_hooks/__init__.py +381 -0
- kivy/tools/packaging/pyinstaller_hooks/__main__.py +29 -0
- kivy/tools/packaging/pyinstaller_hooks/hook-kivy.py +9 -0
- kivy/tools/packaging/pyinstaller_hooks/pyi_rth_kivy.py +17 -0
- kivy/tools/pep8checker/pep8.py +2316 -0
- kivy/tools/pep8checker/pep8kivy.py +109 -0
- kivy/tools/report.py +223 -0
- kivy/tools/stub-gl-debug.py +201 -0
- kivy/tools/texturecompress.py +233 -0
- kivy/uix/__init__.py +56 -0
- kivy/uix/accordion.py +484 -0
- kivy/uix/actionbar.py +934 -0
- kivy/uix/anchorlayout.py +122 -0
- kivy/uix/behaviors/__init__.py +95 -0
- kivy/uix/behaviors/button.py +212 -0
- kivy/uix/behaviors/codenavigation.py +167 -0
- kivy/uix/behaviors/compoundselection.py +688 -0
- kivy/uix/behaviors/cover.py +160 -0
- kivy/uix/behaviors/drag.py +234 -0
- kivy/uix/behaviors/emacs.py +140 -0
- kivy/uix/behaviors/focus.py +595 -0
- kivy/uix/behaviors/knspace.py +590 -0
- kivy/uix/behaviors/togglebutton.py +156 -0
- kivy/uix/behaviors/touchripple.py +318 -0
- kivy/uix/boxlayout.py +331 -0
- kivy/uix/bubble.py +576 -0
- kivy/uix/button.py +137 -0
- kivy/uix/camera.py +118 -0
- kivy/uix/carousel.py +695 -0
- kivy/uix/checkbox.py +197 -0
- kivy/uix/codeinput.py +238 -0
- kivy/uix/colorpicker.py +486 -0
- kivy/uix/dropdown.py +391 -0
- kivy/uix/effectwidget.py +772 -0
- kivy/uix/filechooser.py +1134 -0
- kivy/uix/floatlayout.py +148 -0
- kivy/uix/gesturesurface.py +625 -0
- kivy/uix/gridlayout.py +629 -0
- kivy/uix/image.py +528 -0
- kivy/uix/label.py +1200 -0
- kivy/uix/layout.py +322 -0
- kivy/uix/modalview.py +339 -0
- kivy/uix/pagelayout.py +233 -0
- kivy/uix/popup.py +266 -0
- kivy/uix/progressbar.py +95 -0
- kivy/uix/recycleboxlayout.py +183 -0
- kivy/uix/recyclegridlayout.py +255 -0
- kivy/uix/recyclelayout.py +446 -0
- kivy/uix/recycleview/__init__.py +624 -0
- kivy/uix/recycleview/datamodel.py +194 -0
- kivy/uix/recycleview/layout.py +253 -0
- kivy/uix/recycleview/views.py +423 -0
- kivy/uix/relativelayout.py +324 -0
- kivy/uix/rst.py +1492 -0
- kivy/uix/sandbox.py +198 -0
- kivy/uix/scatter.py +645 -0
- kivy/uix/scatterlayout.py +93 -0
- kivy/uix/screenmanager.py +1275 -0
- kivy/uix/scrollview.py +1288 -0
- kivy/uix/settings.py +1343 -0
- kivy/uix/slider.py +421 -0
- kivy/uix/spinner.py +221 -0
- kivy/uix/splitter.py +430 -0
- kivy/uix/stacklayout.py +331 -0
- kivy/uix/stencilview.py +40 -0
- kivy/uix/switch.py +122 -0
- kivy/uix/tabbedpanel.py +880 -0
- kivy/uix/textinput.py +4049 -0
- kivy/uix/togglebutton.py +37 -0
- kivy/uix/treeview.py +665 -0
- kivy/uix/video.py +302 -0
- kivy/uix/videoplayer.py +697 -0
- kivy/uix/vkeyboard.py +879 -0
- kivy/uix/widget.py +1629 -0
- kivy/utils.py +550 -0
- kivy/vector.py +412 -0
- kivy/weakmethod.py +72 -0
kivy/uix/filechooser.py
ADDED
|
@@ -0,0 +1,1134 @@
|
|
|
1
|
+
'''
|
|
2
|
+
FileChooser
|
|
3
|
+
===========
|
|
4
|
+
|
|
5
|
+
The FileChooser module provides various classes for describing, displaying and
|
|
6
|
+
browsing file systems.
|
|
7
|
+
|
|
8
|
+
Simple widgets
|
|
9
|
+
--------------
|
|
10
|
+
|
|
11
|
+
There are two ready-to-use widgets that provide views of the file system. Each
|
|
12
|
+
of these present the files and folders in a different style.
|
|
13
|
+
|
|
14
|
+
The :class:`FileChooserListView` displays file entries as text items in a
|
|
15
|
+
vertical list, where folders can be collapsed and expanded.
|
|
16
|
+
|
|
17
|
+
.. image:: images/filechooser_list.png
|
|
18
|
+
|
|
19
|
+
The :class:`FileChooserIconView` presents icons and text from left to right,
|
|
20
|
+
wrapping them as required.
|
|
21
|
+
|
|
22
|
+
.. image:: images/filechooser_icon.png
|
|
23
|
+
|
|
24
|
+
They both provide for scrolling, selection and basic user interaction.
|
|
25
|
+
Please refer to the :class:`FileChooserController` for details on supported
|
|
26
|
+
events and properties.
|
|
27
|
+
|
|
28
|
+
Widget composition
|
|
29
|
+
------------------
|
|
30
|
+
|
|
31
|
+
FileChooser classes adopt a
|
|
32
|
+
`MVC <https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller>`_
|
|
33
|
+
design. They are exposed so that you to extend and customize your file chooser
|
|
34
|
+
according to your needs.
|
|
35
|
+
|
|
36
|
+
The FileChooser classes can be categorized as follows:
|
|
37
|
+
|
|
38
|
+
* Models are represented by concrete implementations of the
|
|
39
|
+
:class:`FileSystemAbstract` class, such as the :class:`FileSystemLocal`.
|
|
40
|
+
|
|
41
|
+
* Views are represented by the :class:`FileChooserListLayout` and
|
|
42
|
+
:class:`FileChooserIconLayout` classes. These are used by the
|
|
43
|
+
:class:`FileChooserListView` and :class:`FileChooserIconView` widgets
|
|
44
|
+
respectively.
|
|
45
|
+
|
|
46
|
+
* Controllers are represented by concrete implementations of the
|
|
47
|
+
:class:`FileChooserController`, namely the :class:`FileChooser`,
|
|
48
|
+
:class:`FileChooserIconView` and :class:`FileChooserListView` classes.
|
|
49
|
+
|
|
50
|
+
This means you can define your own views or provide :class:`FileSystemAbstract`
|
|
51
|
+
implementations for alternative file systems for use with these widgets.
|
|
52
|
+
The :class:`FileChooser` can be used as a controller for handling multiple,
|
|
53
|
+
synchronized views of the same path. By combining these elements, you can add
|
|
54
|
+
your own views and file systems and have them easily interact with the existing
|
|
55
|
+
components.
|
|
56
|
+
|
|
57
|
+
Usage example
|
|
58
|
+
-------------
|
|
59
|
+
|
|
60
|
+
main.py
|
|
61
|
+
|
|
62
|
+
.. include:: ../../examples/RST_Editor/main.py
|
|
63
|
+
:literal:
|
|
64
|
+
|
|
65
|
+
editor.kv
|
|
66
|
+
|
|
67
|
+
.. highlight:: kv
|
|
68
|
+
|
|
69
|
+
.. include:: ../../examples/RST_Editor/editor.kv
|
|
70
|
+
:literal:
|
|
71
|
+
|
|
72
|
+
.. versionadded:: 1.0.5
|
|
73
|
+
|
|
74
|
+
.. versionchanged:: 1.2.0
|
|
75
|
+
|
|
76
|
+
In the chooser template, the `controller` is no longer a direct reference
|
|
77
|
+
but a weak-reference. If you are upgrading, you should change the notation
|
|
78
|
+
`root.controller.xxx` to `root.controller().xxx`.
|
|
79
|
+
|
|
80
|
+
'''
|
|
81
|
+
|
|
82
|
+
__all__ = ('FileChooserListView', 'FileChooserIconView',
|
|
83
|
+
'FileChooserListLayout', 'FileChooserIconLayout',
|
|
84
|
+
'FileChooser', 'FileChooserController',
|
|
85
|
+
'FileChooserProgressBase', 'FileSystemAbstract',
|
|
86
|
+
'FileSystemLocal')
|
|
87
|
+
|
|
88
|
+
from weakref import ref
|
|
89
|
+
from time import time
|
|
90
|
+
|
|
91
|
+
from kivy.core.text import DEFAULT_FONT
|
|
92
|
+
from kivy.compat import string_types
|
|
93
|
+
from kivy.factory import Factory
|
|
94
|
+
from kivy.clock import Clock
|
|
95
|
+
from kivy.lang import Builder
|
|
96
|
+
from kivy.logger import Logger
|
|
97
|
+
from kivy.utils import platform as core_platform
|
|
98
|
+
from kivy.uix.floatlayout import FloatLayout
|
|
99
|
+
from kivy.uix.relativelayout import RelativeLayout
|
|
100
|
+
from kivy.uix.screenmanager import ScreenManager, Screen
|
|
101
|
+
from kivy.properties import (
|
|
102
|
+
StringProperty, ListProperty, BooleanProperty, ObjectProperty,
|
|
103
|
+
NumericProperty, AliasProperty)
|
|
104
|
+
import collections.abc
|
|
105
|
+
from os import listdir
|
|
106
|
+
from os.path import (
|
|
107
|
+
basename, join, sep, normpath, expanduser, altsep,
|
|
108
|
+
splitdrive, realpath, getsize, isdir, abspath, isfile, dirname)
|
|
109
|
+
from fnmatch import fnmatch
|
|
110
|
+
|
|
111
|
+
platform = core_platform
|
|
112
|
+
filesize_units = ('B', 'KB', 'MB', 'GB', 'TB')
|
|
113
|
+
|
|
114
|
+
_have_win32file = False
|
|
115
|
+
if platform == 'win':
|
|
116
|
+
# Import that module here as it's not available on non-windows machines.
|
|
117
|
+
# See http://bit.ly/i9klJE except that the attributes are defined in
|
|
118
|
+
# win32file not win32com (bug on page).
|
|
119
|
+
# Note: For some reason this doesn't work after a os.chdir(), no matter to
|
|
120
|
+
# what directory you change from where. Windows weirdness.
|
|
121
|
+
try:
|
|
122
|
+
from win32file import FILE_ATTRIBUTE_HIDDEN, GetFileAttributesExW, \
|
|
123
|
+
error
|
|
124
|
+
_have_win32file = True
|
|
125
|
+
except ImportError:
|
|
126
|
+
Logger.error('filechooser: win32file module is missing')
|
|
127
|
+
Logger.error('filechooser: we cannot check if a file is hidden or not')
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def alphanumeric_folders_first(files, filesystem):
|
|
131
|
+
return (sorted(f for f in files if filesystem.is_dir(f)) +
|
|
132
|
+
sorted(f for f in files if not filesystem.is_dir(f)))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class FileSystemAbstract(object):
|
|
136
|
+
'''Class for implementing a File System view that can be used with the
|
|
137
|
+
:class:`FileChooser <FileChooser>`.
|
|
138
|
+
|
|
139
|
+
.. versionadded:: 1.8.0
|
|
140
|
+
'''
|
|
141
|
+
|
|
142
|
+
def listdir(self, fn):
|
|
143
|
+
'''Return the list of files in the directory `fn`
|
|
144
|
+
'''
|
|
145
|
+
pass
|
|
146
|
+
|
|
147
|
+
def getsize(self, fn):
|
|
148
|
+
'''Return the size in bytes of a file
|
|
149
|
+
'''
|
|
150
|
+
pass
|
|
151
|
+
|
|
152
|
+
def is_hidden(self, fn):
|
|
153
|
+
'''Return True if the file is hidden
|
|
154
|
+
'''
|
|
155
|
+
pass
|
|
156
|
+
|
|
157
|
+
def is_dir(self, fn):
|
|
158
|
+
'''Return True if the argument passed to this method is a directory
|
|
159
|
+
'''
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class FileSystemLocal(FileSystemAbstract):
|
|
164
|
+
'''Implementation of :class:`FileSystemAbstract` for local files.
|
|
165
|
+
|
|
166
|
+
.. versionadded:: 1.8.0
|
|
167
|
+
'''
|
|
168
|
+
|
|
169
|
+
def listdir(self, fn):
|
|
170
|
+
return listdir(fn)
|
|
171
|
+
|
|
172
|
+
def getsize(self, fn):
|
|
173
|
+
return getsize(fn)
|
|
174
|
+
|
|
175
|
+
def is_hidden(self, fn):
|
|
176
|
+
if platform == 'win':
|
|
177
|
+
if not _have_win32file:
|
|
178
|
+
return False
|
|
179
|
+
try:
|
|
180
|
+
return GetFileAttributesExW(fn)[0] & FILE_ATTRIBUTE_HIDDEN
|
|
181
|
+
except error:
|
|
182
|
+
# This error can occurred when a file is already accessed by
|
|
183
|
+
# someone else. So don't return to True, because we have lot
|
|
184
|
+
# of chances to not being able to do anything with it.
|
|
185
|
+
Logger.exception('unable to access to <%s>' % fn)
|
|
186
|
+
return True
|
|
187
|
+
|
|
188
|
+
return basename(fn).startswith('.')
|
|
189
|
+
|
|
190
|
+
def is_dir(self, fn):
|
|
191
|
+
return isdir(fn)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class FileChooserProgressBase(FloatLayout):
|
|
195
|
+
'''Base for implementing a progress view. This view is used when too many
|
|
196
|
+
entries need to be created and are delayed over multiple frames.
|
|
197
|
+
|
|
198
|
+
.. versionadded:: 1.2.0
|
|
199
|
+
'''
|
|
200
|
+
|
|
201
|
+
path = StringProperty('')
|
|
202
|
+
'''Current path of the FileChooser, read-only.
|
|
203
|
+
'''
|
|
204
|
+
|
|
205
|
+
index = NumericProperty(0)
|
|
206
|
+
'''Current index of :attr:`total` entries to be loaded.
|
|
207
|
+
'''
|
|
208
|
+
|
|
209
|
+
total = NumericProperty(1)
|
|
210
|
+
'''Total number of entries to load.
|
|
211
|
+
'''
|
|
212
|
+
|
|
213
|
+
def cancel(self, *largs):
|
|
214
|
+
'''Cancel any action from the FileChooserController.
|
|
215
|
+
'''
|
|
216
|
+
if self.parent:
|
|
217
|
+
self.parent.cancel()
|
|
218
|
+
|
|
219
|
+
def on_touch_down(self, touch):
|
|
220
|
+
if self.collide_point(*touch.pos):
|
|
221
|
+
super(FileChooserProgressBase, self).on_touch_down(touch)
|
|
222
|
+
return True
|
|
223
|
+
|
|
224
|
+
def on_touch_move(self, touch):
|
|
225
|
+
if self.collide_point(*touch.pos):
|
|
226
|
+
super(FileChooserProgressBase, self).on_touch_move(touch)
|
|
227
|
+
return True
|
|
228
|
+
|
|
229
|
+
def on_touch_up(self, touch):
|
|
230
|
+
if self.collide_point(*touch.pos):
|
|
231
|
+
super(FileChooserProgressBase, self).on_touch_up(touch)
|
|
232
|
+
return True
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class FileChooserProgress(FileChooserProgressBase):
|
|
236
|
+
pass
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
class FileChooserLayout(FloatLayout):
|
|
240
|
+
'''Base class for file chooser layouts.
|
|
241
|
+
|
|
242
|
+
.. versionadded:: 1.9.0
|
|
243
|
+
'''
|
|
244
|
+
|
|
245
|
+
VIEWNAME = 'undefined'
|
|
246
|
+
|
|
247
|
+
__events__ = ('on_entry_added', 'on_entries_cleared',
|
|
248
|
+
'on_subentry_to_entry', 'on_remove_subentry', 'on_submit')
|
|
249
|
+
|
|
250
|
+
controller = ObjectProperty()
|
|
251
|
+
'''
|
|
252
|
+
Reference to the controller handling this layout.
|
|
253
|
+
|
|
254
|
+
:class:`~kivy.properties.ObjectProperty`
|
|
255
|
+
'''
|
|
256
|
+
|
|
257
|
+
def on_entry_added(self, node, parent=None):
|
|
258
|
+
pass
|
|
259
|
+
|
|
260
|
+
def on_entries_cleared(self):
|
|
261
|
+
pass
|
|
262
|
+
|
|
263
|
+
def on_subentry_to_entry(self, subentry, entry):
|
|
264
|
+
pass
|
|
265
|
+
|
|
266
|
+
def on_remove_subentry(self, subentry, entry):
|
|
267
|
+
pass
|
|
268
|
+
|
|
269
|
+
def on_submit(self, selected, touch=None):
|
|
270
|
+
pass
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class FileChooserListLayout(FileChooserLayout):
|
|
274
|
+
'''File chooser layout using a list view.
|
|
275
|
+
|
|
276
|
+
.. versionadded:: 1.9.0
|
|
277
|
+
'''
|
|
278
|
+
VIEWNAME = 'list'
|
|
279
|
+
_ENTRY_TEMPLATE = 'FileListEntry'
|
|
280
|
+
|
|
281
|
+
def __init__(self, **kwargs):
|
|
282
|
+
super(FileChooserListLayout, self).__init__(**kwargs)
|
|
283
|
+
self.fbind('on_entries_cleared', self.scroll_to_top)
|
|
284
|
+
|
|
285
|
+
def scroll_to_top(self, *args):
|
|
286
|
+
self.ids.scrollview.scroll_y = 1.0
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
class FileChooserIconLayout(FileChooserLayout):
|
|
290
|
+
'''File chooser layout using an icon view.
|
|
291
|
+
|
|
292
|
+
.. versionadded:: 1.9.0
|
|
293
|
+
'''
|
|
294
|
+
|
|
295
|
+
VIEWNAME = 'icon'
|
|
296
|
+
_ENTRY_TEMPLATE = 'FileIconEntry'
|
|
297
|
+
|
|
298
|
+
def __init__(self, **kwargs):
|
|
299
|
+
super(FileChooserIconLayout, self).__init__(**kwargs)
|
|
300
|
+
self.fbind('on_entries_cleared', self.scroll_to_top)
|
|
301
|
+
|
|
302
|
+
def scroll_to_top(self, *args):
|
|
303
|
+
self.ids.scrollview.scroll_y = 1.0
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
class FileChooserController(RelativeLayout):
|
|
307
|
+
'''Base for implementing a FileChooser. Don't use this class directly, but
|
|
308
|
+
prefer using an implementation such as the :class:`FileChooser`,
|
|
309
|
+
:class:`FileChooserListView` or :class:`FileChooserIconView`.
|
|
310
|
+
|
|
311
|
+
:Events:
|
|
312
|
+
`on_entry_added`: entry, parent
|
|
313
|
+
Fired when a root-level entry is added to the file list. If you
|
|
314
|
+
return True from this event, the entry is not added to FileChooser.
|
|
315
|
+
`on_entries_cleared`
|
|
316
|
+
Fired when the the entries list is cleared, usually when the
|
|
317
|
+
root is refreshed.
|
|
318
|
+
`on_subentry_to_entry`: entry, parent
|
|
319
|
+
Fired when a sub-entry is added to an existing entry or
|
|
320
|
+
when entries are removed from an entry e.g. when
|
|
321
|
+
a node is closed.
|
|
322
|
+
`on_submit`: selection, touch
|
|
323
|
+
Fired when a file has been selected with a double-tap.
|
|
324
|
+
'''
|
|
325
|
+
_ENTRY_TEMPLATE = None
|
|
326
|
+
|
|
327
|
+
layout = ObjectProperty(baseclass=FileChooserLayout)
|
|
328
|
+
'''
|
|
329
|
+
Reference to the layout widget instance.
|
|
330
|
+
|
|
331
|
+
layout is an :class:`~kivy.properties.ObjectProperty`.
|
|
332
|
+
|
|
333
|
+
.. versionadded:: 1.9.0
|
|
334
|
+
'''
|
|
335
|
+
|
|
336
|
+
path = StringProperty(u'/')
|
|
337
|
+
'''
|
|
338
|
+
path is a :class:`~kivy.properties.StringProperty` and defaults to the
|
|
339
|
+
current working directory as a unicode string. It specifies the path on the
|
|
340
|
+
filesystem that this controller should refer to.
|
|
341
|
+
|
|
342
|
+
.. warning::
|
|
343
|
+
|
|
344
|
+
If a unicode path is specified, all the files returned will be in
|
|
345
|
+
unicode, allowing the display of unicode files and paths. If a bytes
|
|
346
|
+
path is specified, only files and paths with ascii names will be
|
|
347
|
+
displayed properly: non-ascii filenames will be displayed and listed
|
|
348
|
+
with questions marks (?) instead of their unicode characters.
|
|
349
|
+
'''
|
|
350
|
+
|
|
351
|
+
filters = ListProperty([])
|
|
352
|
+
'''
|
|
353
|
+
filters specifies the filters to be applied to the files in the directory.
|
|
354
|
+
filters is a :class:`~kivy.properties.ListProperty` and defaults to [].
|
|
355
|
+
This is equivalent to '\\*' i.e. nothing is filtered.
|
|
356
|
+
|
|
357
|
+
The filters are not reset when the path changes. You need to do that
|
|
358
|
+
yourself if desired.
|
|
359
|
+
|
|
360
|
+
There are two kinds of filters: patterns and callbacks.
|
|
361
|
+
|
|
362
|
+
#. Patterns
|
|
363
|
+
|
|
364
|
+
e.g. ['\\*.png'].
|
|
365
|
+
You can use the following patterns:
|
|
366
|
+
|
|
367
|
+
========== =================================
|
|
368
|
+
Pattern Meaning
|
|
369
|
+
========== =================================
|
|
370
|
+
\\* matches everything
|
|
371
|
+
? matches any single character
|
|
372
|
+
[seq] matches any character in seq
|
|
373
|
+
[!seq] matches any character not in seq
|
|
374
|
+
========== =================================
|
|
375
|
+
|
|
376
|
+
#. Callbacks
|
|
377
|
+
|
|
378
|
+
You can specify a function that will be called for each file. The
|
|
379
|
+
callback will be passed the folder and file name as the first
|
|
380
|
+
and second parameters respectively. It should return True to
|
|
381
|
+
indicate a match and False otherwise.
|
|
382
|
+
|
|
383
|
+
.. versionchanged:: 1.4.0
|
|
384
|
+
Added the option to specify the filter as a callback.
|
|
385
|
+
'''
|
|
386
|
+
|
|
387
|
+
filter_dirs = BooleanProperty(False)
|
|
388
|
+
'''
|
|
389
|
+
Indicates whether filters should also apply to directories.
|
|
390
|
+
filter_dirs is a :class:`~kivy.properties.BooleanProperty` and defaults to
|
|
391
|
+
False.
|
|
392
|
+
'''
|
|
393
|
+
|
|
394
|
+
sort_func = ObjectProperty(alphanumeric_folders_first)
|
|
395
|
+
'''
|
|
396
|
+
Provides a function to be called with a list of filenames as the first
|
|
397
|
+
argument and the filesystem implementation as the second argument. It
|
|
398
|
+
returns a list of filenames sorted for display in the view.
|
|
399
|
+
|
|
400
|
+
sort_func is an :class:`~kivy.properties.ObjectProperty` and defaults to a
|
|
401
|
+
function returning alphanumerically named folders first.
|
|
402
|
+
|
|
403
|
+
.. versionchanged:: 1.8.0
|
|
404
|
+
|
|
405
|
+
The signature needs now 2 arguments: first the list of files,
|
|
406
|
+
second the filesystem class to use.
|
|
407
|
+
'''
|
|
408
|
+
|
|
409
|
+
files = ListProperty([])
|
|
410
|
+
'''
|
|
411
|
+
The list of files in the directory specified by path after applying the
|
|
412
|
+
filters.
|
|
413
|
+
|
|
414
|
+
files is a read-only :class:`~kivy.properties.ListProperty`.
|
|
415
|
+
'''
|
|
416
|
+
|
|
417
|
+
show_hidden = BooleanProperty(False)
|
|
418
|
+
'''
|
|
419
|
+
Determines whether hidden files and folders should be shown.
|
|
420
|
+
|
|
421
|
+
show_hidden is a :class:`~kivy.properties.BooleanProperty` and defaults to
|
|
422
|
+
False.
|
|
423
|
+
'''
|
|
424
|
+
|
|
425
|
+
selection = ListProperty([])
|
|
426
|
+
'''
|
|
427
|
+
Contains the list of files that are currently selected.
|
|
428
|
+
|
|
429
|
+
selection is a read-only :class:`~kivy.properties.ListProperty` and
|
|
430
|
+
defaults to [].
|
|
431
|
+
'''
|
|
432
|
+
|
|
433
|
+
multiselect = BooleanProperty(False)
|
|
434
|
+
'''
|
|
435
|
+
Determines whether the user is able to select multiple files or not.
|
|
436
|
+
|
|
437
|
+
multiselect is a :class:`~kivy.properties.BooleanProperty` and defaults to
|
|
438
|
+
False.
|
|
439
|
+
'''
|
|
440
|
+
|
|
441
|
+
dirselect = BooleanProperty(False)
|
|
442
|
+
'''
|
|
443
|
+
Determines whether directories are valid selections or not.
|
|
444
|
+
|
|
445
|
+
dirselect is a :class:`~kivy.properties.BooleanProperty` and defaults to
|
|
446
|
+
False.
|
|
447
|
+
|
|
448
|
+
.. versionadded:: 1.1.0
|
|
449
|
+
'''
|
|
450
|
+
|
|
451
|
+
rootpath = StringProperty(None, allownone=True)
|
|
452
|
+
'''
|
|
453
|
+
Root path to use instead of the system root path. If set, it will not show
|
|
454
|
+
a ".." directory to go up to the root path. For example, if you set
|
|
455
|
+
rootpath to /users/foo, the user will be unable to go to /users or to any
|
|
456
|
+
other directory not starting with /users/foo.
|
|
457
|
+
|
|
458
|
+
rootpath is a :class:`~kivy.properties.StringProperty` and defaults
|
|
459
|
+
to None.
|
|
460
|
+
|
|
461
|
+
.. versionadded:: 1.2.0
|
|
462
|
+
|
|
463
|
+
.. note::
|
|
464
|
+
|
|
465
|
+
Similarly to :attr:`path`, whether `rootpath` is specified as
|
|
466
|
+
bytes or a unicode string determines the type of the filenames and
|
|
467
|
+
paths read.
|
|
468
|
+
'''
|
|
469
|
+
|
|
470
|
+
progress_cls = ObjectProperty(FileChooserProgress)
|
|
471
|
+
'''Class to use for displaying a progress indicator for filechooser
|
|
472
|
+
loading.
|
|
473
|
+
|
|
474
|
+
progress_cls is an :class:`~kivy.properties.ObjectProperty` and defaults to
|
|
475
|
+
:class:`FileChooserProgress`.
|
|
476
|
+
|
|
477
|
+
.. versionadded:: 1.2.0
|
|
478
|
+
|
|
479
|
+
.. versionchanged:: 1.8.0
|
|
480
|
+
|
|
481
|
+
If set to a string, the :class:`~kivy.factory.Factory` will be used to
|
|
482
|
+
resolve the class name.
|
|
483
|
+
|
|
484
|
+
'''
|
|
485
|
+
|
|
486
|
+
file_encodings = ListProperty(
|
|
487
|
+
['utf-8', 'latin1', 'cp1252'], deprecated=True)
|
|
488
|
+
'''Possible encodings for decoding a filename to unicode. In the case that
|
|
489
|
+
the user has a non-ascii filename, undecodable without knowing its
|
|
490
|
+
initial encoding, we have no other choice than to guess it.
|
|
491
|
+
|
|
492
|
+
Please note that if you encounter an issue because of a missing encoding
|
|
493
|
+
here, we'll be glad to add it to this list.
|
|
494
|
+
|
|
495
|
+
file_encodings is a :class:`~kivy.properties.ListProperty` and defaults to
|
|
496
|
+
['utf-8', 'latin1', 'cp1252'].
|
|
497
|
+
|
|
498
|
+
.. versionadded:: 1.3.0
|
|
499
|
+
|
|
500
|
+
.. deprecated:: 1.8.0
|
|
501
|
+
This property is no longer used as the filechooser no longer decodes
|
|
502
|
+
the file names.
|
|
503
|
+
|
|
504
|
+
'''
|
|
505
|
+
|
|
506
|
+
file_system = ObjectProperty(FileSystemLocal(),
|
|
507
|
+
baseclass=FileSystemAbstract)
|
|
508
|
+
'''The file system object used to access the file system. This should be a
|
|
509
|
+
subclass of :class:`FileSystemAbstract`.
|
|
510
|
+
|
|
511
|
+
file_system is an :class:`~kivy.properties.ObjectProperty` and defaults to
|
|
512
|
+
:class:`FileSystemLocal()`
|
|
513
|
+
|
|
514
|
+
.. versionadded:: 1.8.0
|
|
515
|
+
'''
|
|
516
|
+
|
|
517
|
+
font_name = StringProperty(DEFAULT_FONT)
|
|
518
|
+
'''Filename of the font to use in UI components. The path can be
|
|
519
|
+
absolute or relative. Relative paths are resolved by the
|
|
520
|
+
:func:`~kivy.resources.resource_find` function.
|
|
521
|
+
|
|
522
|
+
:attr:`font_name` is a :class:`~kivy.properties.StringProperty` and
|
|
523
|
+
defaults to 'Roboto'. This value is taken
|
|
524
|
+
from :class:`~kivy.config.Config`.
|
|
525
|
+
'''
|
|
526
|
+
|
|
527
|
+
_update_files_ev = None
|
|
528
|
+
_create_files_entries_ev = None
|
|
529
|
+
|
|
530
|
+
__events__ = ('on_entry_added', 'on_entries_cleared',
|
|
531
|
+
'on_subentry_to_entry', 'on_remove_subentry', 'on_submit')
|
|
532
|
+
|
|
533
|
+
def __init__(self, **kwargs):
|
|
534
|
+
self._progress = None
|
|
535
|
+
super(FileChooserController, self).__init__(**kwargs)
|
|
536
|
+
|
|
537
|
+
self._items = []
|
|
538
|
+
fbind = self.fbind
|
|
539
|
+
fbind('selection', self._update_item_selection)
|
|
540
|
+
|
|
541
|
+
self._previous_path = [self.path]
|
|
542
|
+
fbind('path', self._save_previous_path)
|
|
543
|
+
update = self._trigger_update
|
|
544
|
+
fbind('path', update)
|
|
545
|
+
fbind('filters', update)
|
|
546
|
+
fbind('rootpath', update)
|
|
547
|
+
update()
|
|
548
|
+
|
|
549
|
+
def on_touch_down(self, touch):
|
|
550
|
+
# don't respond to touchs outside self
|
|
551
|
+
if not self.collide_point(*touch.pos):
|
|
552
|
+
return
|
|
553
|
+
if self.disabled:
|
|
554
|
+
return True
|
|
555
|
+
return super(FileChooserController, self).on_touch_down(touch)
|
|
556
|
+
|
|
557
|
+
def on_touch_up(self, touch):
|
|
558
|
+
# don't respond to touchs outside self
|
|
559
|
+
if not self.collide_point(*touch.pos):
|
|
560
|
+
return
|
|
561
|
+
if self.disabled:
|
|
562
|
+
return True
|
|
563
|
+
return super(FileChooserController, self).on_touch_up(touch)
|
|
564
|
+
|
|
565
|
+
def _update_item_selection(self, *args):
|
|
566
|
+
for item in self._items:
|
|
567
|
+
item.selected = item.path in self.selection
|
|
568
|
+
|
|
569
|
+
def _save_previous_path(self, instance, value):
|
|
570
|
+
self._previous_path.append(value)
|
|
571
|
+
self._previous_path = self._previous_path[-2:]
|
|
572
|
+
|
|
573
|
+
def _trigger_update(self, *args):
|
|
574
|
+
ev = self._update_files_ev
|
|
575
|
+
if ev is None:
|
|
576
|
+
ev = self._update_files_ev = Clock.create_trigger(
|
|
577
|
+
self._update_files)
|
|
578
|
+
ev()
|
|
579
|
+
|
|
580
|
+
def on_entry_added(self, node, parent=None):
|
|
581
|
+
if self.layout:
|
|
582
|
+
self.layout.dispatch('on_entry_added', node, parent)
|
|
583
|
+
|
|
584
|
+
def on_entries_cleared(self):
|
|
585
|
+
if self.layout:
|
|
586
|
+
self.layout.dispatch('on_entries_cleared')
|
|
587
|
+
|
|
588
|
+
def on_subentry_to_entry(self, subentry, entry):
|
|
589
|
+
if self.layout:
|
|
590
|
+
self.layout.dispatch('on_subentry_to_entry', subentry, entry)
|
|
591
|
+
|
|
592
|
+
def on_remove_subentry(self, subentry, entry):
|
|
593
|
+
if self.layout:
|
|
594
|
+
self.layout.dispatch('on_remove_subentry', subentry, entry)
|
|
595
|
+
|
|
596
|
+
def on_submit(self, selected, touch=None):
|
|
597
|
+
if self.layout:
|
|
598
|
+
self.layout.dispatch('on_submit', selected, touch)
|
|
599
|
+
|
|
600
|
+
def entry_touched(self, entry, touch):
|
|
601
|
+
'''(internal) This method must be called by the template when an entry
|
|
602
|
+
is touched by the user.
|
|
603
|
+
'''
|
|
604
|
+
if (
|
|
605
|
+
'button' in touch.profile and touch.button in (
|
|
606
|
+
'scrollup', 'scrolldown', 'scrollleft', 'scrollright')):
|
|
607
|
+
return False
|
|
608
|
+
|
|
609
|
+
_dir = self.file_system.is_dir(entry.path)
|
|
610
|
+
dirselect = self.dirselect
|
|
611
|
+
|
|
612
|
+
if _dir and dirselect and touch.is_double_tap:
|
|
613
|
+
self.open_entry(entry)
|
|
614
|
+
return
|
|
615
|
+
|
|
616
|
+
if self.multiselect:
|
|
617
|
+
if entry.path in self.selection:
|
|
618
|
+
self.selection.remove(entry.path)
|
|
619
|
+
else:
|
|
620
|
+
if _dir and not self.dirselect:
|
|
621
|
+
self.open_entry(entry)
|
|
622
|
+
return
|
|
623
|
+
self.selection.append(entry.path)
|
|
624
|
+
else:
|
|
625
|
+
if _dir and not self.dirselect:
|
|
626
|
+
return
|
|
627
|
+
self.selection = [abspath(join(self.path, entry.path)), ]
|
|
628
|
+
|
|
629
|
+
def entry_released(self, entry, touch):
|
|
630
|
+
'''(internal) This method must be called by the template when an entry
|
|
631
|
+
is touched by the user.
|
|
632
|
+
|
|
633
|
+
.. versionadded:: 1.1.0
|
|
634
|
+
'''
|
|
635
|
+
if (
|
|
636
|
+
'button' in touch.profile and touch.button in (
|
|
637
|
+
'scrollup', 'scrolldown', 'scrollleft', 'scrollright')):
|
|
638
|
+
return False
|
|
639
|
+
if not self.multiselect:
|
|
640
|
+
if self.file_system.is_dir(entry.path) and not self.dirselect:
|
|
641
|
+
self.open_entry(entry)
|
|
642
|
+
elif touch.is_double_tap:
|
|
643
|
+
if self.dirselect and self.file_system.is_dir(entry.path):
|
|
644
|
+
return
|
|
645
|
+
else:
|
|
646
|
+
self.dispatch('on_submit', self.selection, touch)
|
|
647
|
+
|
|
648
|
+
def open_entry(self, entry):
|
|
649
|
+
try:
|
|
650
|
+
# Just check if we can list the directory. This is also what
|
|
651
|
+
# _add_file does, so if it fails here, it would also fail later
|
|
652
|
+
# on. Do the check here to prevent setting path to an invalid
|
|
653
|
+
# directory that we cannot list.
|
|
654
|
+
self.file_system.listdir(entry.path)
|
|
655
|
+
except OSError:
|
|
656
|
+
entry.locked = True
|
|
657
|
+
else:
|
|
658
|
+
# If entry.path is to jump to previous directory, update path with
|
|
659
|
+
# parent directory
|
|
660
|
+
self.path = abspath(join(self.path, entry.path))
|
|
661
|
+
self.selection = [self.path, ] if self.dirselect else []
|
|
662
|
+
|
|
663
|
+
def _apply_filters(self, files):
|
|
664
|
+
if not self.filters:
|
|
665
|
+
return files
|
|
666
|
+
filtered = []
|
|
667
|
+
for filt in self.filters:
|
|
668
|
+
if isinstance(filt, collections.abc.Callable):
|
|
669
|
+
filtered.extend([fn for fn in files if filt(self.path, fn)])
|
|
670
|
+
else:
|
|
671
|
+
filtered.extend([fn for fn in files if fnmatch(fn, filt)])
|
|
672
|
+
if not self.filter_dirs:
|
|
673
|
+
dirs = [fn for fn in files if self.file_system.is_dir(fn)]
|
|
674
|
+
filtered.extend(dirs)
|
|
675
|
+
return list(set(filtered))
|
|
676
|
+
|
|
677
|
+
def get_nice_size(self, fn):
|
|
678
|
+
'''Pass the filepath. Returns the size in the best human readable
|
|
679
|
+
format or '' if it is a directory (Don't recursively calculate size).
|
|
680
|
+
'''
|
|
681
|
+
if self.file_system.is_dir(fn):
|
|
682
|
+
return ''
|
|
683
|
+
try:
|
|
684
|
+
size = self.file_system.getsize(fn)
|
|
685
|
+
except OSError:
|
|
686
|
+
return '--'
|
|
687
|
+
|
|
688
|
+
for unit in filesize_units:
|
|
689
|
+
if size < 1024.0:
|
|
690
|
+
return '%1.0f %s' % (size, unit)
|
|
691
|
+
size /= 1024.0
|
|
692
|
+
|
|
693
|
+
def _update_files(self, *args, **kwargs):
|
|
694
|
+
# trigger to start gathering the files in the new directory
|
|
695
|
+
# we'll start a timer that will do the job, 10 times per frames
|
|
696
|
+
# (default)
|
|
697
|
+
self._gitems = []
|
|
698
|
+
self._gitems_parent = kwargs.get('parent', None)
|
|
699
|
+
self._gitems_gen = self._generate_file_entries(
|
|
700
|
+
path=kwargs.get('path', self.path),
|
|
701
|
+
parent=self._gitems_parent)
|
|
702
|
+
self.path = abspath(self.path)
|
|
703
|
+
|
|
704
|
+
# cancel any previous clock if exist
|
|
705
|
+
ev = self._create_files_entries_ev
|
|
706
|
+
if ev is not None:
|
|
707
|
+
ev.cancel()
|
|
708
|
+
|
|
709
|
+
# show the progression screen
|
|
710
|
+
self._hide_progress()
|
|
711
|
+
if self._create_files_entries():
|
|
712
|
+
# not enough for creating all the entries, all a clock to continue
|
|
713
|
+
# start a timer for the next 100 ms
|
|
714
|
+
if ev is None:
|
|
715
|
+
ev = self._create_files_entries_ev = Clock.schedule_interval(
|
|
716
|
+
self._create_files_entries, .1)
|
|
717
|
+
ev()
|
|
718
|
+
|
|
719
|
+
def _get_file_paths(self, items):
|
|
720
|
+
return [file.path for file in items]
|
|
721
|
+
|
|
722
|
+
def _create_files_entries(self, *args):
|
|
723
|
+
# create maximum entries during 50ms max, or 10 minimum (slow system)
|
|
724
|
+
# (on a "fast system" (core i7 2700K), we can create up to 40 entries
|
|
725
|
+
# in 50 ms. So 10 is fine for low system.
|
|
726
|
+
start = time()
|
|
727
|
+
finished = False
|
|
728
|
+
index = total = count = 1
|
|
729
|
+
while time() - start < 0.05 or count < 10:
|
|
730
|
+
try:
|
|
731
|
+
index, total, item = next(self._gitems_gen)
|
|
732
|
+
self._gitems.append(item)
|
|
733
|
+
count += 1
|
|
734
|
+
except StopIteration:
|
|
735
|
+
finished = True
|
|
736
|
+
break
|
|
737
|
+
except TypeError: # in case _gitems_gen is None
|
|
738
|
+
finished = True
|
|
739
|
+
break
|
|
740
|
+
|
|
741
|
+
# if this wasn't enough for creating all the entries, show a progress
|
|
742
|
+
# bar, and report the activity to the user.
|
|
743
|
+
if not finished:
|
|
744
|
+
self._show_progress()
|
|
745
|
+
self._progress.total = total
|
|
746
|
+
self._progress.index = index
|
|
747
|
+
return True
|
|
748
|
+
|
|
749
|
+
# we created all the files, now push them on the view
|
|
750
|
+
self._items = items = self._gitems
|
|
751
|
+
parent = self._gitems_parent
|
|
752
|
+
if parent is None:
|
|
753
|
+
self.dispatch('on_entries_cleared')
|
|
754
|
+
for entry in items:
|
|
755
|
+
self.dispatch('on_entry_added', entry, parent)
|
|
756
|
+
else:
|
|
757
|
+
parent.entries[:] = items
|
|
758
|
+
for entry in items:
|
|
759
|
+
self.dispatch('on_subentry_to_entry', entry, parent)
|
|
760
|
+
self.files[:] = self._get_file_paths(items)
|
|
761
|
+
|
|
762
|
+
# stop the progression / creation
|
|
763
|
+
self._hide_progress()
|
|
764
|
+
self._gitems = None
|
|
765
|
+
self._gitems_gen = None
|
|
766
|
+
ev = self._create_files_entries_ev
|
|
767
|
+
if ev is not None:
|
|
768
|
+
ev.cancel()
|
|
769
|
+
return False
|
|
770
|
+
|
|
771
|
+
def cancel(self, *largs):
|
|
772
|
+
'''Cancel any background action started by filechooser, such as loading
|
|
773
|
+
a new directory.
|
|
774
|
+
|
|
775
|
+
.. versionadded:: 1.2.0
|
|
776
|
+
'''
|
|
777
|
+
ev = self._create_files_entries_ev
|
|
778
|
+
if ev is not None:
|
|
779
|
+
ev.cancel()
|
|
780
|
+
|
|
781
|
+
self._hide_progress()
|
|
782
|
+
if len(self._previous_path) > 1:
|
|
783
|
+
# if we cancel any action, the path will be set same as the
|
|
784
|
+
# previous one, so we can safely cancel the update of the previous
|
|
785
|
+
# path.
|
|
786
|
+
self.path = self._previous_path[-2]
|
|
787
|
+
|
|
788
|
+
ev = self._update_files_ev
|
|
789
|
+
if ev is not None:
|
|
790
|
+
ev.cancel()
|
|
791
|
+
|
|
792
|
+
def _show_progress(self):
|
|
793
|
+
if self._progress:
|
|
794
|
+
return
|
|
795
|
+
cls = self.progress_cls
|
|
796
|
+
if isinstance(cls, string_types):
|
|
797
|
+
cls = Factory.get(cls)
|
|
798
|
+
self._progress = cls(path=self.path)
|
|
799
|
+
self._progress.value = 0
|
|
800
|
+
self.add_widget(self._progress)
|
|
801
|
+
|
|
802
|
+
def _hide_progress(self):
|
|
803
|
+
if self._progress:
|
|
804
|
+
self.remove_widget(self._progress)
|
|
805
|
+
self._progress = None
|
|
806
|
+
|
|
807
|
+
def _generate_file_entries(self, *args, **kwargs):
|
|
808
|
+
# Generator that will create all the files entries.
|
|
809
|
+
# the generator is used via _update_files() and _create_files_entries()
|
|
810
|
+
# don't use it directly.
|
|
811
|
+
is_root = False
|
|
812
|
+
path = kwargs.get('path', self.path)
|
|
813
|
+
have_parent = kwargs.get('parent', None) is not None
|
|
814
|
+
|
|
815
|
+
# Add the components that are always needed
|
|
816
|
+
if self.rootpath:
|
|
817
|
+
rootpath = realpath(self.rootpath)
|
|
818
|
+
path = realpath(path)
|
|
819
|
+
if not path.startswith(rootpath):
|
|
820
|
+
self.path = rootpath
|
|
821
|
+
return
|
|
822
|
+
elif path == rootpath:
|
|
823
|
+
is_root = True
|
|
824
|
+
else:
|
|
825
|
+
if platform == 'win':
|
|
826
|
+
is_root = splitdrive(path)[1] in (sep, altsep)
|
|
827
|
+
elif platform in ('macosx', 'linux', 'android', 'ios'):
|
|
828
|
+
is_root = normpath(expanduser(path)) == sep
|
|
829
|
+
else:
|
|
830
|
+
# Unknown fs, just always add the .. entry but also log
|
|
831
|
+
Logger.warning('Filechooser: Unsupported OS: %r' % platform)
|
|
832
|
+
# generate an entries to go back to previous
|
|
833
|
+
if not is_root and not have_parent:
|
|
834
|
+
back = '..' + sep
|
|
835
|
+
if platform == 'win':
|
|
836
|
+
new_path = path[:path.rfind(sep)]
|
|
837
|
+
if sep not in new_path:
|
|
838
|
+
new_path += sep
|
|
839
|
+
pardir = self._create_entry_widget(dict(
|
|
840
|
+
name=back, size='', path=new_path, controller=ref(self),
|
|
841
|
+
isdir=True, parent=None, sep=sep,
|
|
842
|
+
get_nice_size=lambda: ''))
|
|
843
|
+
else:
|
|
844
|
+
pardir = self._create_entry_widget(dict(
|
|
845
|
+
name=back, size='', path=back, controller=ref(self),
|
|
846
|
+
isdir=True, parent=None, sep=sep,
|
|
847
|
+
get_nice_size=lambda: ''))
|
|
848
|
+
yield 0, 1, pardir
|
|
849
|
+
|
|
850
|
+
# generate all the entries for files
|
|
851
|
+
try:
|
|
852
|
+
for index, total, item in self._add_files(path):
|
|
853
|
+
yield index, total, item
|
|
854
|
+
except OSError:
|
|
855
|
+
Logger.exception('Unable to open directory <%s>' % self.path)
|
|
856
|
+
self.files[:] = []
|
|
857
|
+
|
|
858
|
+
def _create_entry_widget(self, ctx):
|
|
859
|
+
template = self.layout._ENTRY_TEMPLATE\
|
|
860
|
+
if self.layout else self._ENTRY_TEMPLATE
|
|
861
|
+
return Builder.template(template, **ctx)
|
|
862
|
+
|
|
863
|
+
def _add_files(self, path, parent=None):
|
|
864
|
+
path = expanduser(path)
|
|
865
|
+
if isfile(path):
|
|
866
|
+
path = dirname(path)
|
|
867
|
+
|
|
868
|
+
files = []
|
|
869
|
+
fappend = files.append
|
|
870
|
+
for f in self.file_system.listdir(path):
|
|
871
|
+
try:
|
|
872
|
+
# In the following, use fully qualified filenames
|
|
873
|
+
fappend(normpath(join(path, f)))
|
|
874
|
+
except UnicodeDecodeError:
|
|
875
|
+
Logger.exception('unable to decode <{}>'.format(f))
|
|
876
|
+
except UnicodeEncodeError:
|
|
877
|
+
Logger.exception('unable to encode <{}>'.format(f))
|
|
878
|
+
# Apply filename filters
|
|
879
|
+
files = self._apply_filters(files)
|
|
880
|
+
# Sort the list of files
|
|
881
|
+
files = self.sort_func(files, self.file_system)
|
|
882
|
+
is_hidden = self.file_system.is_hidden
|
|
883
|
+
if not self.show_hidden:
|
|
884
|
+
files = [x for x in files if not is_hidden(x)]
|
|
885
|
+
self.files[:] = files
|
|
886
|
+
total = len(files)
|
|
887
|
+
wself = ref(self)
|
|
888
|
+
for index, fn in enumerate(files):
|
|
889
|
+
|
|
890
|
+
def get_nice_size():
|
|
891
|
+
# Use a closure for lazy-loading here
|
|
892
|
+
return self.get_nice_size(fn)
|
|
893
|
+
|
|
894
|
+
ctx = {'name': basename(fn),
|
|
895
|
+
'get_nice_size': get_nice_size,
|
|
896
|
+
'path': fn,
|
|
897
|
+
'controller': wself,
|
|
898
|
+
'isdir': self.file_system.is_dir(fn),
|
|
899
|
+
'parent': parent,
|
|
900
|
+
'sep': sep}
|
|
901
|
+
entry = self._create_entry_widget(ctx)
|
|
902
|
+
yield index, total, entry
|
|
903
|
+
|
|
904
|
+
def entry_subselect(self, entry):
|
|
905
|
+
if not self.file_system.is_dir(entry.path):
|
|
906
|
+
return
|
|
907
|
+
self._update_files(path=entry.path, parent=entry)
|
|
908
|
+
|
|
909
|
+
def close_subselection(self, entry):
|
|
910
|
+
for subentry in entry.entries:
|
|
911
|
+
self.dispatch('on_remove_subentry', subentry, entry)
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
class FileChooserListView(FileChooserController):
|
|
915
|
+
'''Implementation of a :class:`FileChooserController` using a list view.
|
|
916
|
+
|
|
917
|
+
.. versionadded:: 1.9.0
|
|
918
|
+
'''
|
|
919
|
+
_ENTRY_TEMPLATE = 'FileListEntry'
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
class FileChooserIconView(FileChooserController):
|
|
923
|
+
'''Implementation of a :class:`FileChooserController` using an icon view.
|
|
924
|
+
|
|
925
|
+
.. versionadded:: 1.9.0
|
|
926
|
+
'''
|
|
927
|
+
_ENTRY_TEMPLATE = 'FileIconEntry'
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
class FileChooser(FileChooserController):
|
|
931
|
+
'''Implementation of a :class:`FileChooserController` which supports
|
|
932
|
+
switching between multiple, synced layout views.
|
|
933
|
+
|
|
934
|
+
The FileChooser can be used as follows:
|
|
935
|
+
|
|
936
|
+
.. code-block:: kv
|
|
937
|
+
|
|
938
|
+
BoxLayout:
|
|
939
|
+
orientation: 'vertical'
|
|
940
|
+
|
|
941
|
+
BoxLayout:
|
|
942
|
+
size_hint_y: None
|
|
943
|
+
height: sp(52)
|
|
944
|
+
|
|
945
|
+
Button:
|
|
946
|
+
text: 'Icon View'
|
|
947
|
+
on_press: fc.view_mode = 'icon'
|
|
948
|
+
Button:
|
|
949
|
+
text: 'List View'
|
|
950
|
+
on_press: fc.view_mode = 'list'
|
|
951
|
+
|
|
952
|
+
FileChooser:
|
|
953
|
+
id: fc
|
|
954
|
+
FileChooserIconLayout
|
|
955
|
+
FileChooserListLayout
|
|
956
|
+
|
|
957
|
+
.. versionadded:: 1.9.0
|
|
958
|
+
'''
|
|
959
|
+
|
|
960
|
+
manager = ObjectProperty()
|
|
961
|
+
'''
|
|
962
|
+
Reference to the :class:`~kivy.uix.screenmanager.ScreenManager` instance.
|
|
963
|
+
|
|
964
|
+
manager is an :class:`~kivy.properties.ObjectProperty`.
|
|
965
|
+
'''
|
|
966
|
+
|
|
967
|
+
_view_list = ListProperty()
|
|
968
|
+
|
|
969
|
+
def get_view_list(self):
|
|
970
|
+
return self._view_list
|
|
971
|
+
|
|
972
|
+
view_list = AliasProperty(get_view_list, bind=('_view_list',))
|
|
973
|
+
'''
|
|
974
|
+
List of views added to this FileChooser.
|
|
975
|
+
|
|
976
|
+
view_list is an :class:`~kivy.properties.AliasProperty` of type
|
|
977
|
+
:class:`list`.
|
|
978
|
+
'''
|
|
979
|
+
|
|
980
|
+
_view_mode = StringProperty()
|
|
981
|
+
|
|
982
|
+
def get_view_mode(self):
|
|
983
|
+
return self._view_mode
|
|
984
|
+
|
|
985
|
+
def set_view_mode(self, mode):
|
|
986
|
+
if mode not in self._view_list:
|
|
987
|
+
raise ValueError('unknown view mode %r' % mode)
|
|
988
|
+
self._view_mode = mode
|
|
989
|
+
|
|
990
|
+
view_mode = AliasProperty(
|
|
991
|
+
get_view_mode, set_view_mode, bind=('_view_mode',))
|
|
992
|
+
'''
|
|
993
|
+
Current layout view mode.
|
|
994
|
+
|
|
995
|
+
view_mode is an :class:`~kivy.properties.AliasProperty` of type
|
|
996
|
+
:class:`str`.
|
|
997
|
+
'''
|
|
998
|
+
|
|
999
|
+
@property
|
|
1000
|
+
def _views(self):
|
|
1001
|
+
return [screen.children[0] for screen in self.manager.screens]
|
|
1002
|
+
|
|
1003
|
+
def __init__(self, **kwargs):
|
|
1004
|
+
super(FileChooser, self).__init__(**kwargs)
|
|
1005
|
+
|
|
1006
|
+
self.manager = ScreenManager()
|
|
1007
|
+
super(FileChooser, self).add_widget(self.manager)
|
|
1008
|
+
|
|
1009
|
+
self.trigger_update_view = Clock.create_trigger(self.update_view)
|
|
1010
|
+
|
|
1011
|
+
self.fbind('view_mode', self.trigger_update_view)
|
|
1012
|
+
|
|
1013
|
+
def add_widget(self, widget, *args, **kwargs):
|
|
1014
|
+
if widget is self._progress:
|
|
1015
|
+
super(FileChooser, self).add_widget(widget, *args, **kwargs)
|
|
1016
|
+
elif hasattr(widget, 'VIEWNAME'):
|
|
1017
|
+
name = widget.VIEWNAME + 'view'
|
|
1018
|
+
screen = Screen(name=name)
|
|
1019
|
+
widget.controller = self
|
|
1020
|
+
screen.add_widget(widget)
|
|
1021
|
+
self.manager.add_widget(screen)
|
|
1022
|
+
|
|
1023
|
+
self.trigger_update_view()
|
|
1024
|
+
else:
|
|
1025
|
+
raise ValueError(
|
|
1026
|
+
'widget must be a FileChooserLayout,'
|
|
1027
|
+
' not %s' % type(widget).__name__)
|
|
1028
|
+
|
|
1029
|
+
def rebuild_views(self):
|
|
1030
|
+
views = [view.VIEWNAME for view in self._views]
|
|
1031
|
+
if views != self._view_list:
|
|
1032
|
+
self._view_list = views
|
|
1033
|
+
if self._view_mode not in self._view_list:
|
|
1034
|
+
self._view_mode = self._view_list[0]
|
|
1035
|
+
self._trigger_update()
|
|
1036
|
+
|
|
1037
|
+
def update_view(self, *args):
|
|
1038
|
+
self.rebuild_views()
|
|
1039
|
+
|
|
1040
|
+
sm = self.manager
|
|
1041
|
+
viewlist = self._view_list
|
|
1042
|
+
view = self.view_mode
|
|
1043
|
+
current = sm.current[:-4]
|
|
1044
|
+
|
|
1045
|
+
viewindex = viewlist.index(view) if view in viewlist else 0
|
|
1046
|
+
currentindex = viewlist.index(current) if current in viewlist else 0
|
|
1047
|
+
|
|
1048
|
+
direction = 'left' if currentindex < viewindex else 'right'
|
|
1049
|
+
|
|
1050
|
+
sm.transition.direction = direction
|
|
1051
|
+
sm.current = view + 'view'
|
|
1052
|
+
|
|
1053
|
+
def _create_entry_widget(self, ctx):
|
|
1054
|
+
return [Builder.template(view._ENTRY_TEMPLATE, **ctx)
|
|
1055
|
+
for view in self._views]
|
|
1056
|
+
|
|
1057
|
+
def _get_file_paths(self, items):
|
|
1058
|
+
if self._views:
|
|
1059
|
+
return [file[0].path for file in items]
|
|
1060
|
+
return []
|
|
1061
|
+
|
|
1062
|
+
def _update_item_selection(self, *args):
|
|
1063
|
+
for viewitem in self._items:
|
|
1064
|
+
selected = viewitem[0].path in self.selection
|
|
1065
|
+
for item in viewitem:
|
|
1066
|
+
item.selected = selected
|
|
1067
|
+
|
|
1068
|
+
def on_entry_added(self, node, parent=None):
|
|
1069
|
+
for index, view in enumerate(self._views):
|
|
1070
|
+
view.dispatch(
|
|
1071
|
+
'on_entry_added',
|
|
1072
|
+
node[index], parent[index] if parent else None)
|
|
1073
|
+
|
|
1074
|
+
def on_entries_cleared(self):
|
|
1075
|
+
for view in self._views:
|
|
1076
|
+
view.dispatch('on_entries_cleared')
|
|
1077
|
+
|
|
1078
|
+
def on_subentry_to_entry(self, subentry, entry):
|
|
1079
|
+
for index, view in enumerate(self._views):
|
|
1080
|
+
view.dispatch('on_subentry_to_entry', subentry[index], entry)
|
|
1081
|
+
|
|
1082
|
+
def on_remove_subentry(self, subentry, entry):
|
|
1083
|
+
for index, view in enumerate(self._views):
|
|
1084
|
+
view.dispatch('on_remove_subentry', subentry[index], entry)
|
|
1085
|
+
|
|
1086
|
+
def on_submit(self, selected, touch=None):
|
|
1087
|
+
view_mode = self.view_mode
|
|
1088
|
+
for view in self._views:
|
|
1089
|
+
if view_mode == view.VIEWNAME:
|
|
1090
|
+
view.dispatch('on_submit', selected, touch)
|
|
1091
|
+
return
|
|
1092
|
+
|
|
1093
|
+
|
|
1094
|
+
if __name__ == '__main__':
|
|
1095
|
+
from kivy.app import App
|
|
1096
|
+
from pprint import pprint
|
|
1097
|
+
import textwrap
|
|
1098
|
+
import sys
|
|
1099
|
+
|
|
1100
|
+
root = Builder.load_string(textwrap.dedent('''\
|
|
1101
|
+
BoxLayout:
|
|
1102
|
+
orientation: 'vertical'
|
|
1103
|
+
|
|
1104
|
+
BoxLayout:
|
|
1105
|
+
size_hint_y: None
|
|
1106
|
+
height: sp(52)
|
|
1107
|
+
|
|
1108
|
+
Button:
|
|
1109
|
+
text: 'Icon View'
|
|
1110
|
+
on_press: fc.view_mode = 'icon'
|
|
1111
|
+
Button:
|
|
1112
|
+
text: 'List View'
|
|
1113
|
+
on_press: fc.view_mode = 'list'
|
|
1114
|
+
|
|
1115
|
+
FileChooser:
|
|
1116
|
+
id: fc
|
|
1117
|
+
|
|
1118
|
+
FileChooserIconLayout
|
|
1119
|
+
FileChooserListLayout
|
|
1120
|
+
'''))
|
|
1121
|
+
|
|
1122
|
+
class FileChooserApp(App):
|
|
1123
|
+
|
|
1124
|
+
def build(self):
|
|
1125
|
+
v = root.ids.fc
|
|
1126
|
+
if len(sys.argv) > 1:
|
|
1127
|
+
v.path = sys.argv[1]
|
|
1128
|
+
|
|
1129
|
+
v.bind(selection=lambda *x: pprint("selection: %s" % x[1:]))
|
|
1130
|
+
v.bind(path=lambda *x: pprint("path: %s" % x[1:]))
|
|
1131
|
+
|
|
1132
|
+
return root
|
|
1133
|
+
|
|
1134
|
+
FileChooserApp().run()
|