├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── cadnano2 ├── README.md ├── __init__.py ├── cadnano.bat ├── cadnano.py ├── cadnanoqt.py ├── controllers │ ├── __init__.py │ ├── documentcontroller.py │ ├── itemcontrollers │ │ ├── __init__.py │ │ ├── activesliceitemcontroller.py │ │ ├── partitemcontroller.py │ │ ├── strand │ │ │ ├── __init__.py │ │ │ ├── abstractstranditemcontroller.py │ │ │ ├── endpointitemcontroller.py │ │ │ ├── stranditemcontroller.py │ │ │ └── xoveritemcontroller.py │ │ └── virtualhelixitemcontroller.py │ ├── mayacontrollers │ │ ├── __init__.py │ │ ├── helixManip.py │ │ ├── mayaObjectManager.py │ │ ├── mayaSelectionContex.py │ │ └── removedMsgCmd.py │ └── viewrootcontroller.py ├── data │ ├── __init__.py │ ├── dnasequences.py │ └── mayadefaultmodules.txt ├── dummyqt │ ├── QtCore.py │ ├── QtGui.py │ └── __init__.py ├── icons │ ├── add-bases.svg │ ├── cadnano2-app-icon.ico │ ├── cadnano2-app-icon.png │ ├── cadnano2-app-icon_shelf.png │ ├── cadnano2-document-icon.ico │ ├── cadnano2-document-icon.png │ ├── cadnano2-icon_doc-legacy.png │ ├── cadnano2_installer-bkg.png │ ├── data-export-staples.png │ ├── data-new_32.png │ ├── data-open_32.png │ ├── data-save_32.png │ ├── data-svg.png │ ├── export-staples.png │ ├── export-staples.svg │ ├── part-filter-endpoint.png │ ├── part-filter-handle.png │ ├── part-filter-part.png │ ├── part-filter-scaf.png │ ├── part-filter-stap.png │ ├── part-filter-strand.png │ ├── part-filter-xover.png │ ├── part-new-honeycomb.png │ ├── part-new-square.png │ ├── path-addseq.png │ ├── path-addseq.svg │ ├── path-autobreak.png │ ├── path-break_48.png │ ├── path-edit_32.png │ ├── path-erase_32.png │ ├── path-erase_48x48.png │ ├── path-force-xover.png │ ├── path-frame.png │ ├── path-insert.png │ ├── path-insert_48x48.png │ ├── path-loop.png │ ├── path-loop_48.png │ ├── path-modify.png │ ├── path-modify.svg │ ├── path-move.png │ ├── path-paint_48.png │ ├── path-pen_48.png │ ├── path-sequence.png │ ├── path-skip.png │ ├── path-skip_48x48.png │ ├── path-staple.png │ ├── remove-bases.svg │ ├── slice-delete-last.png │ ├── slice-edit.png │ ├── slice-go-first.png │ ├── slice-go-last.png │ ├── slice-move.png │ ├── slice-renumber.png │ └── source │ │ ├── cadnano2-icon.pdf │ │ ├── part-filter-endpoint.ai │ │ ├── part-filter-handle.ai │ │ ├── part-filter-scaf.ai │ │ ├── part-filter-stap.ai │ │ ├── part-filter-strand.ai │ │ ├── part-filter-xover.ai │ │ ├── part-new-honeycomb.ai │ │ ├── part-new-square.ai │ │ ├── path-addseq.ai │ │ ├── path-break.ai │ │ ├── path-frame.ai │ │ ├── path-insert.ai │ │ ├── path-loop.ai │ │ ├── path-paint.ai │ │ ├── path-sequence.ai │ │ └── path-skip.ai ├── include │ ├── __init__.py │ ├── fetchfile.py │ └── getdependencies.py ├── main.py ├── model │ ├── __init__.py │ ├── decorators │ │ ├── __init__.py │ │ ├── decorator.py │ │ ├── insertion.py │ │ └── modifier.py │ ├── document.py │ ├── enum.py │ ├── io │ │ ├── __init__.py │ │ ├── decoder.py │ │ ├── encoder.py │ │ ├── legacydecoder.py │ │ └── legacyencoder.py │ ├── oligo.py │ ├── parts │ │ ├── __init__.py │ │ ├── honeycombpart.py │ │ ├── part.py │ │ └── squarepart.py │ ├── strand.py │ ├── strandset.py │ └── virtualhelix.py ├── osx │ ├── CNApplicationDelegate.py │ └── __init__.py ├── plugins │ ├── autobreak │ │ ├── Makefile │ │ ├── __init__.py │ │ ├── autobreak.py │ │ ├── autobreakconfig.py │ │ ├── autobreakconfig.ui │ │ ├── autobreakconfig_ui.py │ │ └── staplegraph.py │ └── test.py ├── spCadNano.py ├── tests │ ├── __init__.py │ ├── cadnanoguitestcase.py │ ├── functionaltestinputs │ │ ├── Nature09_monolith.csv │ │ ├── Nature09_monolith.json │ │ ├── Nature09_squarenut.csv │ │ ├── Nature09_squarenut.json │ │ ├── Science09_beachball_v1.csv │ │ ├── Science09_beachball_v1.json │ │ ├── Science09_prot120_98_v3.csv │ │ ├── Science09_prot120_98_v3.json │ │ ├── __init__.py │ │ ├── gap_vs_skip.csv │ │ ├── gap_vs_skip.json │ │ ├── loop_size_1.csv │ │ ├── loop_size_1.json │ │ ├── loops_and_skips.csv │ │ ├── loops_and_skips.json │ │ ├── simple42.csv │ │ ├── simple42legacy.csv │ │ ├── simple42legacy.json │ │ ├── skip.csv │ │ └── skip.json │ ├── functionaltests.py │ ├── guitestcase.py │ ├── modeltests.py │ ├── runall.py │ ├── unittests.py │ └── xmlrunner.py ├── ui │ ├── Makefile │ ├── __init__.py │ ├── dialogs │ │ ├── __init__.py │ │ ├── about.ui │ │ ├── addseq.ui │ │ ├── dialogicons_rc.py.bak │ │ ├── images │ │ │ ├── cadnano2-about.png │ │ │ ├── part-honeycomb.png │ │ │ ├── part-square.png │ │ │ ├── path-addseq.svg │ │ │ ├── path-edit_32.png │ │ │ ├── path-force-xover.png │ │ │ ├── path-paint_48.png │ │ │ └── source │ │ │ │ └── cadnano2-about.ai │ │ ├── latticetype.ui │ │ ├── preferences.ui │ │ ├── ui.dialogs.dialogicons.qrc │ │ ├── ui_about.py │ │ ├── ui_addseq.py │ │ ├── ui_latticetype.py │ │ ├── ui_preferences.py │ │ ├── ui_warning.py │ │ └── warning.ui │ └── mainwindow │ │ ├── __init__.py │ │ ├── icons_rc.py │ │ ├── images │ │ ├── add-bases.svg │ │ ├── cadnano2-app-icon.ico │ │ ├── cadnano2-app-icon.png │ │ ├── cadnano2-app-icon_shelf.png │ │ ├── cadnano2-document-icon.ico │ │ ├── cadnano2-document-icon.png │ │ ├── cadnano2-icon_doc-legacy.png │ │ ├── cadnano2_installer-bkg.png │ │ ├── data-export-staples.png │ │ ├── data-new_32.png │ │ ├── data-open_32.png │ │ ├── data-save_32.png │ │ ├── data-svg.png │ │ ├── export-staples.png │ │ ├── export-staples.svg │ │ ├── part-filter-endpoint.png │ │ ├── part-filter-handle.png │ │ ├── part-filter-part.png │ │ ├── part-filter-scaf.png │ │ ├── part-filter-stap.png │ │ ├── part-filter-strand.png │ │ ├── part-filter-xover.png │ │ ├── part-new-honeycomb.png │ │ ├── part-new-square.png │ │ ├── path-addseq.png │ │ ├── path-addseq.svg │ │ ├── path-autobreak.png │ │ ├── path-break_48.png │ │ ├── path-edit_32.png │ │ ├── path-erase_32.png │ │ ├── path-erase_48x48.png │ │ ├── path-force-xover.png │ │ ├── path-frame.png │ │ ├── path-insert.png │ │ ├── path-insert_48x48.png │ │ ├── path-loop.png │ │ ├── path-loop_48.png │ │ ├── path-modify.png │ │ ├── path-modify.svg │ │ ├── path-move.png │ │ ├── path-paint_48.png │ │ ├── path-pen_48.png │ │ ├── path-sequence.png │ │ ├── path-skip.png │ │ ├── path-skip_48x48.png │ │ ├── path-staple.png │ │ ├── remove-bases.svg │ │ ├── slice-delete-last.png │ │ ├── slice-edit.png │ │ ├── slice-go-first.png │ │ ├── slice-go-last.png │ │ ├── slice-move.png │ │ ├── slice-renumber.png │ │ └── source │ │ │ ├── cadnano2-icon.pdf │ │ │ ├── part-filter-endpoint.ai │ │ │ ├── part-filter-handle.ai │ │ │ ├── part-filter-scaf.ai │ │ │ ├── part-filter-stap.ai │ │ │ ├── part-filter-strand.ai │ │ │ ├── part-filter-xover.ai │ │ │ ├── part-new-honeycomb.ai │ │ │ ├── part-new-square.ai │ │ │ ├── path-addseq.ai │ │ │ ├── path-break.ai │ │ │ ├── path-frame.ai │ │ │ ├── path-insert.ai │ │ │ ├── path-loop.ai │ │ │ ├── path-paint.ai │ │ │ ├── path-sequence.ai │ │ │ └── path-skip.ai │ │ ├── mainwindow.ui │ │ ├── svgbutton.py │ │ ├── ui.mainwindow.icons.qrc │ │ └── ui_mainwindow.py ├── util.py └── views │ ├── QGraphicsScene-event-dispatching-overview.txt │ ├── __init__.py │ ├── customqgraphicsview.py │ ├── documentwindow.py │ ├── pathview │ ├── __init__.py │ ├── activesliceitem.py │ ├── colorpanel.py │ ├── partitem.py │ ├── pathrootitem.py │ ├── pathselection.py │ ├── prexoveritem.py │ ├── strand │ │ ├── __init__.py │ │ ├── abstractstranditem.py │ │ ├── decorators │ │ │ ├── __init__.py │ │ │ ├── abstractdecoratoritem.py │ │ │ ├── fluorophoreitem.py │ │ │ ├── insertionitem.py │ │ │ ├── skipitem.py │ │ │ └── stapleextensionitem.py │ │ ├── endpointitem.py │ │ ├── stranditem.py │ │ └── xoveritem.py │ ├── tools │ │ ├── __init__.py │ │ ├── abstractpathtool.py │ │ ├── addseqtool.py │ │ ├── breaktool.py │ │ ├── erasetool.py │ │ ├── insertiontool.py │ │ ├── painttool.py │ │ ├── pathtoolmanager.py │ │ ├── penciltool.py │ │ ├── selecttool.py │ │ └── skiptool.py │ ├── virtualhelixhandleitem.py │ └── virtualhelixitem.py │ ├── preferences.py │ ├── sliceview │ ├── __init__.py │ ├── activesliceitem.py │ ├── emptyhelixitem.py │ ├── partitem.py │ ├── slicerootitem.py │ ├── tools │ │ ├── __init__.py │ │ └── slicetoolmanager.py │ └── virtualhelixitem.py │ ├── solidview │ ├── __init__.py │ ├── halfcylinderhelixnode.py │ ├── mayaHotKeys.py │ ├── mayaUI.py │ ├── partitem.py │ ├── predecoratornode.py │ ├── solidrootitem.py │ ├── stranditem.py │ └── virtualhelixitem.py │ └── styles.py ├── dist ├── cadnano2-2.4.0-py3-none-any.whl └── cadnano2-2.4.0.tar.gz └── pyproject.toml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | __pycache__ 3 | *.pyc 4 | *.egg-info 5 | build 6 | dist 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.4.0 2 | 3 | * Migrated to PyQt6 4 | * Packaged for PyPI and pip install 5 | 6 | ## 2.0.1 7 | 8 | * Fixed circular scaffold highlighting when opening from an nno file. 9 | * OSX: Reconnected objc bridge so files open via double-click or dock icon drop. 10 | * Fixed bug in display of square-lattice crossover locations. 11 | * Square lattice canvas extension now happens in 32-base steps. 12 | * Updated icon for AddSeq Tool. 13 | * Moved Frame button to the View menu and moved AutoStaple button to the top toolbar. 14 | 15 | 16 | ## 2.0.0 17 | 18 | * Undo/redo. 19 | * Unified interface for square-lattice and honeycomb-lattice parts. The new workflow is to open a document and then click the "Honeycomb" or "Square" button on the top toolbar to create a new part for editing. 20 | * Stored user preferences. 21 | * Scroll to zoom (e.g. via mousewheel). Command+mouse-drag to pan. 22 | * Pencil tool: Left-click to create or destroy staple or scaffold. Right-click to create a forced crossover. 23 | * DNA sequences are displayed live in the interface. 24 | * Export button: creates a staple csv file, replacing the old SeqTool copy-to-clipboard dialog. 25 | * Frame button: zoom-to-fit of path view. 26 | * New file format (.nno extension) 27 | * Loop is renamed to Insert. Its size can be edited in place via its numeric label. 28 | * Multiple helices can be reordered by selecting the helix labels (leftmost orange circle) and dragging the group. 29 | * Delete-Last button removed. To delete a helix, selecting its label and press delete. 30 | * 3D view is removed. See planned features for future replacement. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2011 Wyss Institute at Harvard University and University of California San Francisco 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | http://www.opensource.org/licenses/mit-license.php 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cadnano2 DNA Origami Design Software 2 | 3 | ## Overview 4 | [Cadnano](http://cadnano.org/) is computer-aided design software for DNA origami nanostructures. The original citation is [here](https://academic.oup.com/nar/article/37/15/5001/2409858). 5 | 6 | ## Installation 7 | 8 | **macOS** 9 | * Install [homebrew](https://brew.sh/) 10 | * Install python3: `brew install python3` 11 | * Create a virtualenv: `python3 -m venv ~/virtualenvs/cn24x` 12 | * Activate virtualenv: `source ~/virtualenvs/cn24x/bin/activate` 13 | * Install via pip: `pip3 install cadnano2` 14 | 15 | **Linux** 16 | * Create a virtual env: `python3 -m venv ~/virtualenvs/cn24x` 17 | * Activate the venv: `source ~/virtualenvs/cn24x/bin/activate` 18 | * Install from PyPI: `pip3 install cadnano2` 19 | 20 | **Windows** (tested for Python 3.10.4) 21 | * Download and install latest [python3](https://www.python.org/downloads/) 22 | * Use "Manage app execution aliases" to disable launching "App Installer" via any python executables. 23 | * Add python app folder to your system path, e.g. `C:\Users\shawn\AppData\Local\Programs\Python\Python310\` 24 | * Add scripts folder to your system path, e.g. `C:\Users\shawn\AppData\Local\Programs\Python\Python310\Scripts\` 25 | * Open command prompt (cmd.exe) and confirm you can run "python" and "pip". 26 | * Install Cadnano via pip: `pip install cadnano2` 27 | 28 | ## Running 29 | 30 | **macOS or Linux** 31 | * Open the Terminal 32 | * (macOS or Linux) Activate virtual env: 33 | - `source ~/virtualenvs/cn24x/bin/activate` 34 | * Run the app: `cadnano2` 35 | 36 | **Windows** 37 | * Open the Command Prompt 38 | * Run the app: `cadnano2` 39 | 40 | **macOS alias** 41 | * Add to `~/.zprofile`: `alias cn2="source ~/virtualenvs/cn24x/bin/activate && cadnano2"` 42 | * Open new Terminal and run: `cn2` 43 | 44 | ## Upgrading 45 | * Open the Terminal 46 | * Activate virtual env: `source ~/virtualenvs/cn24x/bin/activate` 47 | * Upgrade via pip: `pip install --upgrade cadnano2` 48 | 49 | 50 | ## Development 51 | 52 | **Setup a dev environment (Mac or Linux)** 53 | 54 | * Create a virtualenv: `python3 -m venv ~/virtualenvs/cn24dev` 55 | * Activate virtualenv: `source ~/virtualenvs/cn24dev/bin/activate` 56 | * Install build dependencies: `pip install setuptools wheel pyqt6` 57 | * Clone repo: `git clone git@github.com:douglaslab/cadnano2.git` 58 | * Change directory: `cd cadnano2` 59 | * Make desired code edits 60 | * Build and install: `pip install -e .` 61 | * Test: `cadnano2` 62 | * Repeat previous 3 steps as needed 63 | 64 | **Setup a dev environment (Windows)** 65 | 66 | * Install venv: `pip install virtualenv` 67 | * Create a virtualenv: `python -m venv virtualenvs\cn24dev` (e.g. in %homepath%) 68 | * Activate virtualenv: `virtualenvs\cn24dev\Scripts\activate` 69 | * Install build dependencies: `pip install setuptools wheel pyqt6` 70 | * Clone repo: `git clone git@github.com:douglaslab/cadnano2.git` 71 | * Change directory: `cd cadnano2` 72 | * Make desired code edits 73 | * Build and install: `pip install -e .` 74 | * Test: `cadnano2` 75 | * Repeat previous 3 steps as needed 76 | 77 | 78 | **Build new dist and upload to PyPi** 79 | 80 | * `pip install build twine` <- install [build](https://pypi.org/project/build/) and [twine](https://pypi.org/project/twine/) 81 | * `cd /path/to/cadnano2/` 82 | * `python3 -m build` creates dist/cadnano2-x.y.z.tar.gz and cadnano2-x.y.z-py3-none-any.whl 83 | * `python3 -m twine upload dist/cadnano2-x.y.z*` 84 | 85 | ## Version notes 86 | 87 | This version of Cadnano2 is maintained by the [Douglas Lab](http://bionano.ucsf.edu/). It is derived from [cadnano/cadnano2](https://github.com/cadnano/cadnano2). 88 | 89 | If you wish to use the Cadnano Python API for scripting, see [cadnano2.5](https://github.com/douglaslab/cadnano2.5/). 90 | 91 | ## License 92 | 93 | This version of Cadnano2 is available under the MIT License. GUI code that uses PyQt6 is GPLv3 as [required](http://pyqt.sourceforge.net/Docs/PyQt6/introduction.html#license) by Riverbank Computing. 94 | -------------------------------------------------------------------------------- /cadnano2/README.md: -------------------------------------------------------------------------------- 1 | # Cadnano2 DNA Origami Software (PyQt6 port) 2 | 3 | ## Overview 4 | [Cadnano](http://cadnano.org/) is computer-aided design software for DNA origami nanostructures. The original citation is [here](https://academic.oup.com/nar/article/37/15/5001/2409858). 5 | 6 | This version of Cadnano2 is being maintained by the [Douglas Lab](http://bionano.ucsf.edu/) to preserve the lattice-based design interface for research purposes. This is not a direct fork of [cadnano/cadnano2](https://github.com/cadnano/cadnano2) because that would result in a 200+ MB download when cloning. We have removed the [installer](https://github.com/cadnano/cadnano2/tree/master/installer) directory and git history, which makes this version less than 3 MB to download, or 11 MB uncompressed. 7 | 8 | If you wish to use the newest version of Cadnano that supports Python scripting and non-lattice designs, see [cadnano2.5](https://github.com/cadnano/cadnano2.5/). 9 | 10 | ## License 11 | 12 | This version of Cadnano2 is available under the MIT License. 13 | GUI code that uses PyQt6 or PyQt3D is GPLv3 as [required](http://pyqt.sourceforge.net/Docs/PyQt6/introduction.html#license) by Riverbank Computing. 14 | -------------------------------------------------------------------------------- /cadnano2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/__init__.py -------------------------------------------------------------------------------- /cadnano2/cadnano.bat: -------------------------------------------------------------------------------- 1 | start pythonw main.py %1 %2 %3 %4 2 | exit -------------------------------------------------------------------------------- /cadnano2/cadnano.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os.path 3 | from glob import glob 4 | from code import interact 5 | import cadnano2.util as util 6 | 7 | sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))+"/include") 8 | 9 | global sharedApp 10 | sharedApp = None 11 | 12 | 13 | def ignoreEnv(): 14 | return environ.get('CADNANO_IGNORE_ENV_VARS_EXCEPT_FOR_ME', False) 15 | 16 | # The global application object used when cadnano is run as a python module 17 | 18 | class HeadlessCadnano(object): 19 | undoGroup = None 20 | def isInMaya(self): 21 | return False 22 | class prefs(): 23 | squareRows = 50 24 | squareCols = 50 25 | def isGui(self): 26 | return False 27 | # end def 28 | 29 | def app(appArgs=None): 30 | global sharedApp 31 | if sharedApp != None: 32 | return sharedApp 33 | return initAppWithoutGui(appArgs) 34 | 35 | def initAppWithoutGui(appArgs=sys.argv): 36 | global sharedApp 37 | sharedApp = HeadlessCadnano() 38 | # loadAllPlugins() 39 | return sharedApp 40 | 41 | def initAppWithGui(appArgs=sys.argv): 42 | util.qtFrameworkList = ['PyQt', 'PySide'] 43 | from .cadnanoqt import CadnanoQt 44 | global sharedApp 45 | sharedApp = CadnanoQt(appArgs) 46 | sharedApp.finishInit() 47 | if util.isWindows(): 48 | pass 49 | # import ctypes 50 | # myappid = 'harvard.cadnano.cadnano2.2' # arbitrary string 51 | # ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid) 52 | return sharedApp 53 | 54 | def initAppMaya(appArgs=sys.argv): 55 | import cadnano2.util as util 56 | util.qtFrameworkList = ['PyQt', 'PySide'] 57 | from cadnanoqt import CadnanoQt 58 | global sharedApp 59 | sharedApp = CadnanoQt(appArgs) 60 | return sharedApp 61 | # end def 62 | 63 | def path(): 64 | return os.path.abspath(os.path.dirname(__file__)) 65 | 66 | # maps plugin path (extension stripped) -> plugin module 67 | loadedPlugins = {} 68 | 69 | def unloadedPlugins(): 70 | """ Returns a list of plugin paths that have yet to 71 | be loaded but are in the top level of one of the 72 | search directories specified in pluginDirs""" 73 | internalPlugins = os.path.join(path(), 'plugins') 74 | pluginDirs = [internalPlugins] 75 | results = [] 76 | for pluginDir in pluginDirs: 77 | if not os.path.isdir(pluginDir): 78 | continue 79 | for dirent in os.listdir(pluginDir): 80 | f = os.path.join(pluginDir, dirent) 81 | isfile = os.path.isfile(f) 82 | hasValidSuffix = dirent.endswith(('.py', '.so')) 83 | if isfile and hasValidSuffix: 84 | results.append(f) 85 | if os.path.isdir(f) and\ 86 | os.path.isfile(os.path.join(f, '__init__.py')): 87 | results.append(f) 88 | return [x for x in results if x not in loadedPlugins] 89 | 90 | # Plugins are no longer supported, so needn't import imp 91 | 92 | # def loadPlugin(f): 93 | # path, fname = os.path.split(f) 94 | # name, ext = os.path.splitext(fname) 95 | # pluginKey = os.path.join(path, name) 96 | # try: 97 | # mod = loadedPlugins[pluginKey] 98 | # return mod 99 | # except KeyError: 100 | # pass 101 | # file, filename, data = imp.find_module(name, [path]) 102 | # mod = imp.load_module(name, file, filename, data) 103 | # loadedPlugins[pluginKey] = mod 104 | # return mod 105 | 106 | # def loadAllPlugins(): 107 | # loadedAPlugin = False 108 | # for p in unloadedPlugins(): 109 | # loadPlugin(p) 110 | # loadedAPlugin = True 111 | # return loadedAPlugin -------------------------------------------------------------------------------- /cadnano2/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/controllers/__init__.py -------------------------------------------------------------------------------- /cadnano2/controllers/itemcontrollers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/controllers/itemcontrollers/__init__.py -------------------------------------------------------------------------------- /cadnano2/controllers/itemcontrollers/activesliceitemcontroller.py: -------------------------------------------------------------------------------- 1 | class ActiveSliceItemController(object): 2 | def __init__(self, activeSliceItem, modelPart): 3 | self._activeSliceItem = activeSliceItem 4 | self._modelPart = modelPart 5 | self.connectSignals() 6 | 7 | def connectSignals(self): 8 | aSI = self._activeSliceItem 9 | mP = self._modelPart 10 | 11 | mP.partActiveSliceResizeSignal.connect(aSI.updateRectSlot) 12 | mP.partActiveSliceIndexSignal.connect(aSI.updateIndexSlot) 13 | mP.partStrandChangedSignal.connect(aSI.strandChangedSlot) 14 | # end def 15 | 16 | def disconnectSignals(self): 17 | aSI = self._activeSliceItem 18 | mP = self._modelPart 19 | 20 | mP.partActiveSliceResizeSignal.disconnect(aSI.updateRectSlot) 21 | mP.partActiveSliceIndexSignal.disconnect(aSI.updateIndexSlot) 22 | mP.partStrandChangedSignal.disconnect(aSI.strandChangedSlot) 23 | # end def 24 | # end class 25 | -------------------------------------------------------------------------------- /cadnano2/controllers/itemcontrollers/partitemcontroller.py: -------------------------------------------------------------------------------- 1 | class PartItemController(object): 2 | def __init__(self, partItem, modelPart): 3 | self._partItem = partItem 4 | self._modelPart = modelPart 5 | self.connectSignals() 6 | 7 | def connectSignals(self): 8 | mP = self._modelPart 9 | pI = self._partItem 10 | 11 | if hasattr(pI, "partHideSlot"): 12 | mP.partHideSignal.connect(pI.partHideSlot) 13 | if hasattr(pI, "partActiveVirtualHelixChangedSlot"): 14 | mP.partActiveVirtualHelixChangedSignal.connect(pI.partActiveVirtualHelixChangedSlot) 15 | 16 | mP.partDimensionsChangedSignal.connect(pI.partDimensionsChangedSlot) 17 | mP.partParentChangedSignal.connect(pI.partParentChangedSlot) 18 | mP.partPreDecoratorSelectedSignal.connect(pI.partPreDecoratorSelectedSlot) 19 | mP.partRemovedSignal.connect(pI.partRemovedSlot) 20 | mP.partStrandChangedSignal.connect(pI.updatePreXoverItemsSlot) 21 | mP.partVirtualHelixAddedSignal.connect(pI.partVirtualHelixAddedSlot) 22 | mP.partVirtualHelixRenumberedSignal.connect(pI.partVirtualHelixRenumberedSlot) 23 | mP.partVirtualHelixResizedSignal.connect(pI.partVirtualHelixResizedSlot) 24 | mP.partVirtualHelicesReorderedSignal.connect(pI.partVirtualHelicesReorderedSlot) 25 | # end def 26 | 27 | def disconnectSignals(self): 28 | mP = self._modelPart 29 | pI = self._partItem 30 | 31 | if hasattr(pI, "partHideSlot"): 32 | mP.partHideSignal.disconnect(pI.partHideSlot) 33 | if hasattr(pI, "partActiveVirtualHelixChangedSlot"): 34 | mP.partActiveVirtualHelixChangedSignal.disconnect(pI.partActiveVirtualHelixChangedSlot) 35 | 36 | mP.partDimensionsChangedSignal.disconnect(pI.partDimensionsChangedSlot) 37 | mP.partParentChangedSignal.disconnect(pI.partParentChangedSlot) 38 | mP.partPreDecoratorSelectedSignal.disconnect(pI.partPreDecoratorSelectedSlot) 39 | mP.partRemovedSignal.disconnect(pI.partRemovedSlot) 40 | mP.partStrandChangedSignal.disconnect(pI.updatePreXoverItemsSlot) 41 | mP.partVirtualHelixAddedSignal.disconnect(pI.partVirtualHelixAddedSlot) 42 | mP.partVirtualHelixRenumberedSignal.disconnect(pI.partVirtualHelixRenumberedSlot) 43 | mP.partVirtualHelixResizedSignal.disconnect(pI.partVirtualHelixResizedSlot) 44 | mP.partVirtualHelicesReorderedSignal.disconnect(pI.partVirtualHelicesReorderedSlot) 45 | # end def 46 | # end class 47 | -------------------------------------------------------------------------------- /cadnano2/controllers/itemcontrollers/strand/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/controllers/itemcontrollers/strand/__init__.py -------------------------------------------------------------------------------- /cadnano2/controllers/itemcontrollers/strand/abstractstranditemcontroller.py: -------------------------------------------------------------------------------- 1 | import cadnano2.util as util 2 | # from cadnano2.controllers.itemcontrollers.abstractitemcontroller import AbstractItemController 3 | 4 | 5 | class AbstractStrandItemController(object): 6 | def __init__(self, strandItem, modelStrand): 7 | """ 8 | Do not call connectSignals here. subclasses 9 | will install two sets of signals. 10 | """ 11 | if self.__class__ == AbstractStrandItemController: 12 | e = "AbstractStrandItemController should be subclassed." 13 | raise NotImplementedError(e) 14 | self._strandItem = strandItem 15 | self._modelStrand = modelStrand 16 | self._modelOligo = modelStrand.oligo() 17 | # end def 18 | 19 | def reconnectOligoSignals(self): 20 | self.disconnectOligoSignals() 21 | self.connectOligoSignals() 22 | # end def 23 | 24 | def connectSignals(self): 25 | """Connects modelStrant signals to strandItem slots.""" 26 | mS = self._modelStrand 27 | sI = self._strandItem 28 | 29 | AbstractStrandItemController.connectOligoSignals(self) 30 | mS.strandHasNewOligoSignal.connect(sI.strandHasNewOligoSlot) 31 | mS.strandRemovedSignal.connect(sI.strandRemovedSlot) 32 | 33 | mS.strandInsertionAddedSignal.connect(sI.strandInsertionAddedSlot) 34 | mS.strandInsertionChangedSignal.connect(sI.strandInsertionChangedSlot) 35 | mS.strandInsertionRemovedSignal.connect(sI.strandInsertionRemovedSlot) 36 | mS.strandDecoratorAddedSignal.connect(sI.strandDecoratorAddedSlot) 37 | mS.strandDecoratorChangedSignal.connect(sI.strandDecoratorChangedSlot) 38 | mS.strandDecoratorRemovedSignal.connect(sI.strandDecoratorRemovedSlot) 39 | mS.strandModifierAddedSignal.connect(sI.strandModifierAddedSlot) 40 | mS.strandModifierChangedSignal.connect(sI.strandModifierChangedSlot) 41 | mS.strandModifierRemovedSignal.connect(sI.strandModifierRemovedSlot) 42 | 43 | mS.selectedChangedSignal.connect(sI.selectedChangedSlot) 44 | # end def 45 | 46 | def connectOligoSignals(self): 47 | sI = self._strandItem 48 | mO = self._modelStrand.oligo() 49 | self._modelOligo = mO 50 | mO.oligoAppearanceChangedSignal.connect(sI.oligoAppearanceChangedSlot) 51 | # end def 52 | 53 | def disconnectSignals(self): 54 | mS = self._modelStrand 55 | sI = self._strandItem 56 | 57 | AbstractStrandItemController.disconnectOligoSignals(self) 58 | mS.strandHasNewOligoSignal.disconnect(sI.strandHasNewOligoSlot) 59 | mS.strandRemovedSignal.disconnect(sI.strandRemovedSlot) 60 | 61 | mS.strandInsertionAddedSignal.disconnect(sI.strandInsertionAddedSlot) 62 | mS.strandInsertionChangedSignal.disconnect(sI.strandInsertionChangedSlot) 63 | mS.strandInsertionRemovedSignal.disconnect(sI.strandInsertionRemovedSlot) 64 | mS.strandDecoratorAddedSignal.disconnect(sI.strandDecoratorAddedSlot) 65 | mS.strandDecoratorChangedSignal.disconnect(sI.strandDecoratorChangedSlot) 66 | mS.strandDecoratorRemovedSignal.disconnect(sI.strandDecoratorRemovedSlot) 67 | mS.strandModifierAddedSignal.disconnect(sI.strandModifierAddedSlot) 68 | mS.strandModifierChangedSignal.disconnect(sI.strandModifierChangedSlot) 69 | mS.strandModifierRemovedSignal.disconnect(sI.strandModifierRemovedSlot) 70 | 71 | mS.selectedChangedSignal.disconnect(sI.selectedChangedSlot) 72 | # end def 73 | 74 | def disconnectOligoSignals(self): 75 | sI = self._strandItem 76 | mO = self._modelOligo 77 | mO.oligoAppearanceChangedSignal.disconnect(sI.oligoAppearanceChangedSlot) 78 | # end def 79 | -------------------------------------------------------------------------------- /cadnano2/controllers/itemcontrollers/strand/endpointitemcontroller.py: -------------------------------------------------------------------------------- 1 | from cadnano2.controllers.itemcontrollers.strand.abstractstranditemcontroller \ 2 | import AbstractStrandItemController 3 | 4 | 5 | class EndpointItemController(AbstractStrandItemController): 6 | def __init__(self, strandItem, modelOligo, modelStrand): 7 | super(EndpointItemController, self).__init__(strandItem, modelStrand) 8 | self.connectSignals() 9 | # end def 10 | -------------------------------------------------------------------------------- /cadnano2/controllers/itemcontrollers/strand/stranditemcontroller.py: -------------------------------------------------------------------------------- 1 | import cadnano2.util as util 2 | from cadnano2.controllers.itemcontrollers.strand.abstractstranditemcontroller \ 3 | import AbstractStrandItemController 4 | 5 | 6 | class StrandItemController(AbstractStrandItemController): 7 | def __init__(self, strandItem, modelStrand): 8 | super(StrandItemController, self).__init__(strandItem, modelStrand) 9 | self.connectSignals() 10 | # end def 11 | 12 | def reconnectOligoSignals(self): 13 | """ 14 | use this for whenever a strands oligo changes 15 | """ 16 | AbstractStrandItemController.disconnectOligoSignals(self) 17 | self.disconnectOligoSignals() 18 | AbstractStrandItemController.connectOligoSignals(self) 19 | self.connectOligoSignals() 20 | # end def 21 | 22 | def connectSignals(self): 23 | AbstractStrandItemController.connectSignals(self) 24 | mS = self._modelStrand 25 | sI = self._strandItem 26 | mS.strandResizedSignal.connect(sI.strandResizedSlot) 27 | # mS.strandXover5pChangedSignal.connect(sI.strandXover5pChangedSlot) 28 | mS.strandUpdateSignal.connect(sI.strandUpdateSlot) 29 | self.connectOligoSignals() 30 | # end def 31 | 32 | def connectOligoSignals(self): 33 | mO = self._modelStrand.oligo() 34 | self._modelOligo = mO 35 | sI = self._strandItem 36 | mO.oligoSequenceAddedSignal.connect(sI.oligoSequenceAddedSlot) 37 | mO.oligoSequenceClearedSignal.connect(sI.oligoSequenceClearedSlot) 38 | # end def 39 | 40 | def disconnectSignals(self): 41 | AbstractStrandItemController.disconnectSignals(self) 42 | mS = self._modelStrand 43 | sI = self._strandItem 44 | mS.strandResizedSignal.disconnect(sI.strandResizedSlot) 45 | # mS.strandXover5pChangedSignal.disconnect(sI.strandXover5pChangedSlot) 46 | mS.strandUpdateSignal.disconnect(sI.strandUpdateSlot) 47 | self.disconnectOligoSignals() 48 | # end def 49 | 50 | def disconnectOligoSignals(self): 51 | mO = self._modelOligo 52 | sI = self._strandItem 53 | mO.oligoSequenceAddedSignal.disconnect(sI.oligoSequenceAddedSlot) 54 | mO.oligoSequenceClearedSignal.disconnect(sI.oligoSequenceClearedSlot) 55 | # end def 56 | -------------------------------------------------------------------------------- /cadnano2/controllers/itemcontrollers/strand/xoveritemcontroller.py: -------------------------------------------------------------------------------- 1 | import cadnano2.util as util 2 | 3 | 4 | class XoverItemController(object): 5 | def __init__(self, xoverItem, modelStrand5p): 6 | self._xoverItem = xoverItem 7 | self._modelStrand5p = modelStrand5p 8 | self._modelOligo = modelStrand5p.oligo() 9 | self.connectSignals() 10 | # end def 11 | 12 | def reconnectOligoSignals(self): 13 | """ 14 | use this for whenever a strands oligo changes 15 | """ 16 | self.disconnectSignals() 17 | self.connectSignals() 18 | # end def 19 | 20 | def reconnectSignals(self, strand): 21 | self.disconnectSignals() 22 | self._modelStrand5p = strand 23 | self.connectSignals() 24 | # end def 25 | 26 | def connectSignals(self): 27 | xI = self._xoverItem 28 | s5p = self._modelStrand5p 29 | mO = s5p.oligo() 30 | self._modelOligo = mO 31 | 32 | s5p.strand5pHasSwappedSignal.connect(xI.strandSwapSlot) 33 | s5p.strandHasNewOligoSignal.connect(xI.strandHasNewOligoSlot) 34 | mO.oligoAppearanceChangedSignal.connect(xI.oligoAppearanceChangedSlot) 35 | s5p.strandXover5pRemovedSignal.connect(xI.xover5pRemovedSlot) 36 | # end def 37 | 38 | def disconnectSignals(self): 39 | xI = self._xoverItem 40 | s5p = self._modelStrand5p 41 | mO = self._modelOligo 42 | 43 | s5p.strand5pHasSwappedSignal.disconnect(xI.strandSwapSlot) 44 | s5p.strandHasNewOligoSignal.disconnect(xI.strandHasNewOligoSlot) 45 | mO.oligoAppearanceChangedSignal.disconnect(xI.oligoAppearanceChangedSlot) 46 | s5p.strandXover5pRemovedSignal.connect(xI.xover5pRemovedSlot) 47 | # end def 48 | -------------------------------------------------------------------------------- /cadnano2/controllers/itemcontrollers/virtualhelixitemcontroller.py: -------------------------------------------------------------------------------- 1 | class VirtualHelixItemController(): 2 | def __init__(self, virtualHelixItem, modelVirtualHelix): 3 | self._virtualHelixItem = virtualHelixItem 4 | self._modelVirtualHelix = modelVirtualHelix 5 | self.connectSignals() 6 | # end def 7 | 8 | def connectSignals(self): 9 | vhItem = self._virtualHelixItem 10 | mvh = self._modelVirtualHelix 11 | 12 | mvh.virtualHelixNumberChangedSignal.connect(vhItem.virtualHelixNumberChangedSlot) 13 | mvh.virtualHelixRemovedSignal.connect(vhItem.virtualHelixRemovedSlot) 14 | 15 | for strandSet in mvh.getStrandSets(): 16 | strandSet.strandsetStrandAddedSignal.connect(vhItem.strandAddedSlot) 17 | # strandSet.decoratorAddedSignal.connect(vhItem.decoratorAddedSlot) 18 | # end def 19 | 20 | def disconnectSignals(self): 21 | vhItem = self._virtualHelixItem 22 | mvh = self._modelVirtualHelix 23 | 24 | mvh.virtualHelixNumberChangedSignal.disconnect(vhItem.virtualHelixNumberChangedSlot) 25 | mvh.virtualHelixRemovedSignal.disconnect(vhItem.virtualHelixRemovedSlot) 26 | 27 | for strandSet in mvh.getStrandSets(): 28 | strandSet.strandsetStrandAddedSignal.disconnect(vhItem.strandAddedSlot) 29 | # strandSet.decoratorAddedSignal.disconnect(vhItem.decoratorAddedSlot) -------------------------------------------------------------------------------- /cadnano2/controllers/mayacontrollers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/controllers/mayacontrollers/__init__.py -------------------------------------------------------------------------------- /cadnano2/controllers/viewrootcontroller.py: -------------------------------------------------------------------------------- 1 | class ViewRootController(): 2 | def __init__(self, viewRoot, modelDocument): 3 | self._viewRoot = viewRoot 4 | self._modelDocument = modelDocument 5 | self.connectSignals() 6 | 7 | def connectSignals(self): 8 | mD = self._modelDocument 9 | vR = self._viewRoot 10 | mD.documentPartAddedSignal.connect(vR.partAddedSlot) 11 | mD.documentClearSelectionsSignal.connect(vR.clearSelectionsSlot) 12 | mD.documentSelectionFilterChangedSignal.connect(vR.selectionFilterChangedSlot) 13 | mD.documentViewResetSignal.connect(vR.resetRootItemSlot) 14 | 15 | def disconnectSignals(self): 16 | mD = self._modelDocument 17 | vR = self._viewRoot 18 | mD.documentPartAddedSignal.disconnect(vR.partAddedSlot) 19 | mD.documentClearSelectionsSignal.disconnect(vR.clearSelectionsSlot) 20 | mD.documentSelectionFilterChangedSignal.disconnect(vR.selectionFilterChangedSlot) 21 | mD.documentViewResetSignal.disconnect(vR.resetRootItemSlot) -------------------------------------------------------------------------------- /cadnano2/data/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | """ 3 | __init__.py 4 | 5 | Created by Shawn Douglas on 2011-01-23. 6 | 7 | """ 8 | -------------------------------------------------------------------------------- /cadnano2/data/mayadefaultmodules.txt: -------------------------------------------------------------------------------- 1 | heapq 2 | maya.app.startup.traceback 3 | maya.app.os 4 | functools 5 | _bisect 6 | maya.types 7 | logging.os 8 | encodings.encodings 9 | maya.OpenMaya 10 | collections 11 | logging.thread 12 | _sre 13 | zipimport 14 | maya 15 | string 16 | SocketServer 17 | maya.sys 18 | maya.app.general.sys 19 | maya.app.general.threading 20 | maya.app.general.cPickle 21 | maya.app.general.types 22 | maya.app.general.CommandPort 23 | bisect 24 | signal 25 | threading 26 | cStringIO 27 | logging.threading 28 | maya._OpenMaya 29 | maya.weakref 30 | atexit 31 | maya.mel 32 | encodings 33 | logging.traceback 34 | abc 35 | maya.standalone 36 | re 37 | select 38 | logging.string 39 | UserDict 40 | new 41 | maya.app.general.StringIO 42 | maya.app.commands 43 | maya.cmds 44 | maya.app.startup.os 45 | maya.re 46 | swig_runtime_data3 47 | maya.traceback 48 | Queue 49 | codecs 50 | logging.sys 51 | maya.app.general.socket 52 | _functools 53 | logging 54 | socket 55 | thread 56 | StringIO 57 | traceback 58 | weakref 59 | itertools 60 | maya.app.general.SocketServer 61 | os 62 | maya.app.startup.atexit 63 | _collections 64 | maya.app.startup.basic 65 | maya.app.startup.maya 66 | maya.app.general.operator 67 | __builtin__ 68 | maya.app.general.time 69 | maya.app.baseUI 70 | maya.app.general 71 | operator 72 | maya.app.sys 73 | _heapq 74 | maya.new 75 | posixpath 76 | errno 77 | _socket 78 | sre_constants 79 | logging.codecs 80 | os.path 81 | maya.mel.melutils 82 | _warnings 83 | maya.logging 84 | cPickle 85 | encodings.__builtin__ 86 | _codecs 87 | maya.app.maya 88 | maya.app.general.select 89 | logging.atexit 90 | maya.app.startup 91 | maya.app.general.maya 92 | maya.app.startup.gui 93 | keyword 94 | logging.time 95 | posix 96 | encodings.aliases 97 | exceptions 98 | sre_parse 99 | copy_reg 100 | sre_compile 101 | logging.cStringIO 102 | maya.utils 103 | site 104 | __main__ 105 | logging.types 106 | maya.app.general.Queue 107 | strop 108 | maya.maya 109 | maya.app 110 | encodings.codecs 111 | _abcoll 112 | genericpath 113 | stat 114 | _ssl 115 | warnings 116 | encodings.ascii 117 | time 118 | encodings.utf_8 119 | sys 120 | maya.os 121 | types 122 | _weakref 123 | maya.app.startup.sys 124 | maya.app.general.errno 125 | maya.app.general.os 126 | linecache 127 | maya.test 128 | maya.OpenMayaRender 129 | maya._OpenMayaRender 130 | PyQt4.QtGui 131 | PyQt4.QtCore 132 | PyQt4 133 | maya._OpenMayaUI 134 | maya.OpenMayaUI 135 | sip 136 | json 137 | model.exceptions 138 | model.collections 139 | ui -------------------------------------------------------------------------------- /cadnano2/dummyqt/QtCore.py: -------------------------------------------------------------------------------- 1 | QObject = object 2 | 3 | class Qt(object): 4 | pass 5 | 6 | class pyqtSignal(object): 7 | def __init__(self, *args): 8 | """ We don't actually do anything with argtypes because 9 | the real Qt will perform checks in the Gui version of 10 | cadnano which should suffice. """ 11 | self.signalEmitters = {} 12 | self.argtypes = args 13 | def __get__(self, emitter): 14 | try: 15 | return self.signalEmitters.get(emitter) 16 | except KeyError: 17 | self.signalEmitters[emitter] = pyqtBoundSignal() 18 | return emitter 19 | 20 | class pyqtBoundSignal(object): 21 | def __init__(self): 22 | self.targets = {} 23 | def connect(self, target): 24 | self.targets.add(target) 25 | def disconnect(self, target): 26 | self.targets.remove(target) 27 | def emit(self, *args): 28 | for t in self.targets: 29 | t(*args) -------------------------------------------------------------------------------- /cadnano2/dummyqt/QtGui.py: -------------------------------------------------------------------------------- 1 | class QUndoCommand(object): 2 | children = [] 3 | name = "untitled" 4 | def undo(self): 5 | for c in reversed(self.children): 6 | c.undo() 7 | def redo(self): 8 | for c in self.children: 9 | c.redo() 10 | 11 | class QUndoStack(object): 12 | undoCmds = [] 13 | macroStack = [] # list of lists 14 | macroNameStack = [] 15 | index = 0 16 | clean = True 17 | def isClean(self): 18 | return self.clean 19 | def setClean(self): 20 | self.clean = True 21 | def clean(self): 22 | self.clean = True 23 | self.undoCmds = [] 24 | self.index = 0 25 | def beginMacro(self, macroName): 26 | self.macroStack.append([]) 27 | self.macroNameStack.append(macroName) 28 | self.clean = False 29 | def push(self, cmd): 30 | if self.macroStack: 31 | self.macroStack[-1].append(cmd) 32 | else: 33 | self.undoCmds.append(cmd) 34 | self.index = len(self.undoCmds) - 1 35 | cmd.redo() 36 | self.clean = False 37 | def endMacro(self): 38 | l = len(self.macroStack) 39 | if l == 0: 40 | assert(False) # Can't end a macro that wasn't begun 41 | cmd = QUndoCommand() 42 | cmd.children = self.macroStack.pop() 43 | cmd.name = self.macroNameStack.pop() 44 | if l == 1: 45 | self.undoCmds.append(cmd) 46 | self.index = len(self.undoCmds) - 1 47 | else: 48 | self.macroStack[-1].append(cmd) 49 | self.clean = False 50 | def undo(self): 51 | assert(not self.macroStack) # Can't undo in the middle of a macro! 52 | if self.index > 0: 53 | cmd = self.undoCmds[self.index] 54 | self.index = self.index - 1 55 | cmd.undo() 56 | def redo(self): 57 | assert(not macroStack) # Can't redo in the middle of a macro 58 | if self.index < len(self.undoCmds) - 1: 59 | cmd = self.undoCmds[self.index + 1] 60 | self.index = self.index + 1 61 | cmd.redo() 62 | 63 | class QColor(object): 64 | r = 0 65 | g = 0 66 | b = 0 67 | a = 0 68 | def __init__(self, *args): 69 | if len(args) == 1: 70 | assert(type(args[0]) == str) 71 | hvals = re.findall('[0-9a-fA-F]{2}', args[0]) 72 | hvals = [int(hv, 16) for hv in hvals] 73 | elif len(args) == 3: 74 | hvals = list(args) 75 | elif len(args) == 4: 76 | hvals = list(args) 77 | else: 78 | hvals = [] 79 | while len(hvals) < 3: 80 | hvals.append(0) 81 | if len(hvals) < 4: 82 | hvals.append(255) 83 | for hv in hvals: 84 | assert(0 <= hv <= 255) 85 | r, g, b, a = hvals 86 | 87 | class QFont(object): 88 | dummy = True 89 | Bold = None 90 | def __init__(self, *args): 91 | pass 92 | 93 | class QFontMetricsF(object): 94 | def __init__(self, *args): 95 | pass 96 | -------------------------------------------------------------------------------- /cadnano2/dummyqt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/dummyqt/__init__.py -------------------------------------------------------------------------------- /cadnano2/icons/add-bases.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 75 | 76 | -------------------------------------------------------------------------------- /cadnano2/icons/cadnano2-app-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/cadnano2-app-icon.ico -------------------------------------------------------------------------------- /cadnano2/icons/cadnano2-app-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/cadnano2-app-icon.png -------------------------------------------------------------------------------- /cadnano2/icons/cadnano2-app-icon_shelf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/cadnano2-app-icon_shelf.png -------------------------------------------------------------------------------- /cadnano2/icons/cadnano2-document-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/cadnano2-document-icon.ico -------------------------------------------------------------------------------- /cadnano2/icons/cadnano2-document-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/cadnano2-document-icon.png -------------------------------------------------------------------------------- /cadnano2/icons/cadnano2-icon_doc-legacy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/cadnano2-icon_doc-legacy.png -------------------------------------------------------------------------------- /cadnano2/icons/cadnano2_installer-bkg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/cadnano2_installer-bkg.png -------------------------------------------------------------------------------- /cadnano2/icons/data-export-staples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/data-export-staples.png -------------------------------------------------------------------------------- /cadnano2/icons/data-new_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/data-new_32.png -------------------------------------------------------------------------------- /cadnano2/icons/data-open_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/data-open_32.png -------------------------------------------------------------------------------- /cadnano2/icons/data-save_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/data-save_32.png -------------------------------------------------------------------------------- /cadnano2/icons/data-svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/data-svg.png -------------------------------------------------------------------------------- /cadnano2/icons/export-staples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/export-staples.png -------------------------------------------------------------------------------- /cadnano2/icons/export-staples.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /cadnano2/icons/part-filter-endpoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/part-filter-endpoint.png -------------------------------------------------------------------------------- /cadnano2/icons/part-filter-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/part-filter-handle.png -------------------------------------------------------------------------------- /cadnano2/icons/part-filter-part.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/part-filter-part.png -------------------------------------------------------------------------------- /cadnano2/icons/part-filter-scaf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/part-filter-scaf.png -------------------------------------------------------------------------------- /cadnano2/icons/part-filter-stap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/part-filter-stap.png -------------------------------------------------------------------------------- /cadnano2/icons/part-filter-strand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/part-filter-strand.png -------------------------------------------------------------------------------- /cadnano2/icons/part-filter-xover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/part-filter-xover.png -------------------------------------------------------------------------------- /cadnano2/icons/part-new-honeycomb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/part-new-honeycomb.png -------------------------------------------------------------------------------- /cadnano2/icons/part-new-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/part-new-square.png -------------------------------------------------------------------------------- /cadnano2/icons/path-addseq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-addseq.png -------------------------------------------------------------------------------- /cadnano2/icons/path-addseq.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /cadnano2/icons/path-autobreak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-autobreak.png -------------------------------------------------------------------------------- /cadnano2/icons/path-break_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-break_48.png -------------------------------------------------------------------------------- /cadnano2/icons/path-edit_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-edit_32.png -------------------------------------------------------------------------------- /cadnano2/icons/path-erase_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-erase_32.png -------------------------------------------------------------------------------- /cadnano2/icons/path-erase_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-erase_48x48.png -------------------------------------------------------------------------------- /cadnano2/icons/path-force-xover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-force-xover.png -------------------------------------------------------------------------------- /cadnano2/icons/path-frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-frame.png -------------------------------------------------------------------------------- /cadnano2/icons/path-insert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-insert.png -------------------------------------------------------------------------------- /cadnano2/icons/path-insert_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-insert_48x48.png -------------------------------------------------------------------------------- /cadnano2/icons/path-loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-loop.png -------------------------------------------------------------------------------- /cadnano2/icons/path-loop_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-loop_48.png -------------------------------------------------------------------------------- /cadnano2/icons/path-modify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-modify.png -------------------------------------------------------------------------------- /cadnano2/icons/path-move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-move.png -------------------------------------------------------------------------------- /cadnano2/icons/path-paint_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-paint_48.png -------------------------------------------------------------------------------- /cadnano2/icons/path-pen_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-pen_48.png -------------------------------------------------------------------------------- /cadnano2/icons/path-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-sequence.png -------------------------------------------------------------------------------- /cadnano2/icons/path-skip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-skip.png -------------------------------------------------------------------------------- /cadnano2/icons/path-skip_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-skip_48x48.png -------------------------------------------------------------------------------- /cadnano2/icons/path-staple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/path-staple.png -------------------------------------------------------------------------------- /cadnano2/icons/remove-bases.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /cadnano2/icons/slice-delete-last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/slice-delete-last.png -------------------------------------------------------------------------------- /cadnano2/icons/slice-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/slice-edit.png -------------------------------------------------------------------------------- /cadnano2/icons/slice-go-first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/slice-go-first.png -------------------------------------------------------------------------------- /cadnano2/icons/slice-go-last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/slice-go-last.png -------------------------------------------------------------------------------- /cadnano2/icons/slice-move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/slice-move.png -------------------------------------------------------------------------------- /cadnano2/icons/slice-renumber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/slice-renumber.png -------------------------------------------------------------------------------- /cadnano2/icons/source/cadnano2-icon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/cadnano2-icon.pdf -------------------------------------------------------------------------------- /cadnano2/icons/source/part-filter-endpoint.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/part-filter-endpoint.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/part-filter-handle.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/part-filter-handle.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/part-filter-scaf.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/part-filter-scaf.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/part-filter-stap.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/part-filter-stap.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/part-filter-strand.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/part-filter-strand.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/part-filter-xover.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/part-filter-xover.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/part-new-honeycomb.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/part-new-honeycomb.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/part-new-square.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/part-new-square.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/path-addseq.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/path-addseq.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/path-break.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/path-break.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/path-frame.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/path-frame.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/path-insert.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/path-insert.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/path-loop.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/path-loop.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/path-paint.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/path-paint.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/path-sequence.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/path-sequence.ai -------------------------------------------------------------------------------- /cadnano2/icons/source/path-skip.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/icons/source/path-skip.ai -------------------------------------------------------------------------------- /cadnano2/include/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/include/__init__.py -------------------------------------------------------------------------------- /cadnano2/include/fetchfile.py: -------------------------------------------------------------------------------- 1 | from urllib.request import Request, urlopen 2 | from urllib.error import URLError, HTTPError 3 | import sys 4 | from os.path import basename, dirname, splitext, exists 5 | import os 6 | import shutil 7 | import tarfile 8 | 9 | def fetchFile(filename, baseurl, filemode='b', filetype='gz', filepath=None): 10 | """ 11 | 12 | filepath - is optional file path location to store the fetched file 13 | """ 14 | # create the url and the request 15 | url = baseurl + '/' + filename 16 | request = Request(url) 17 | 18 | # Open the url 19 | try: 20 | f_url = urlopen(request) 21 | print("downloading " + url) 22 | 23 | # Open our local file for writing 24 | f_dest = open(filename, "w" + filemode) 25 | 26 | # Write to our local file 27 | f_dest.write(f_url.read()) 28 | f_dest.close() 29 | 30 | # handle errors 31 | except HTTPError as e: 32 | print("HTTP Error:", e.code , url) 33 | except URLError as e: 34 | print("URL Error:", e.reason , url) 35 | 36 | filename_out = filename 37 | # unzip if possible 38 | if filetype == 'gz': 39 | 40 | # get the extracted folder name 41 | filename_out = splitext(filename)[0] 42 | temp = splitext(filename_out) 43 | if temp[1] == '.tar': 44 | filename_out = temp[0] 45 | 46 | # open the archive 47 | try: 48 | f_zip= tarfile.open(filename, mode='r') 49 | except tarfile.ReadError as e: 50 | print("unable to read archive", e.code) 51 | print("extracting " + filename_out) 52 | try: 53 | if filepath: 54 | # remove existing folder 55 | if os.path.exists(filepath + '/' + filename_out): 56 | print("file exists") 57 | shutil.rmtree(filepath + '/' + filename_out) 58 | else: 59 | print("file does not exist", filename_out) 60 | f_zip.extractall(path=filepath) 61 | else: 62 | # remove existing folder 63 | if os.path.exists(filename_out): 64 | print("file exists") 65 | shutil.rmtree(filename_out) 66 | else: 67 | print("file does not exist", filename_out) 68 | f_zip.extractall() 69 | except tarfile.ExtractError as e: 70 | print("unable to extract archive", e.code) 71 | f_zip.close() 72 | # remove the archive 73 | print("removing the downloaded archive", filename) 74 | os.remove(filename) 75 | print("done") 76 | return filename_out 77 | # end def 78 | 79 | if __name__ == '__main__': 80 | argv = sys.argv 81 | url = argv[1] 82 | filename = basename(url) 83 | base_url = dirname(url) 84 | fetchFile(filename, base_url) 85 | 86 | -------------------------------------------------------------------------------- /cadnano2/include/getdependencies.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | from .fetchfile import fetchFile 5 | import shutil 6 | from os.path import basename, dirname, splitext, exists, split, abspath 7 | import os 8 | 9 | # list of tuples of the url and the subdirectory to copy to the include directory 10 | urls = [('http://pypi.python.org/packages/source/n/networkx/networkx-1.6.tar.gz', 'networkx') 11 | ] 12 | 13 | # this is intended to be run in the include folder of cadnano2 14 | if __name__ == '__main__': 15 | for urlBlock in urls: 16 | url, subfolder_name = urlBlock 17 | filename = basename(url) 18 | base_url = dirname(url) 19 | folder = fetchFile(filename, base_url) 20 | this_dirname, this_filename = split(abspath(__file__)) 21 | os.chdir(this_dirname) 22 | if subfolder_name: 23 | subfolder_path = folder + '/' + subfolder_name 24 | # remove existing folder 25 | if os.path.exists(subfolder_name): 26 | print("file exists") 27 | shutil.rmtree(subfolder_name) 28 | else: 29 | print("file does not exist", subfolder_name) 30 | shutil.move(subfolder_path, subfolder_name) 31 | shutil.rmtree(folder) 32 | # end for 33 | -------------------------------------------------------------------------------- /cadnano2/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | main.py 5 | 6 | Created by Shawn Douglas on 2010-09-26. 7 | """ 8 | 9 | import sys 10 | import os 11 | from importlib.metadata import version 12 | sys.path.insert(0, '.') 13 | from . import cadnano 14 | 15 | if "-t" in sys.argv: 16 | os.environ['CADNANO_IGNORE_ENV_VARS_EXCEPT_FOR_ME'] = 'YES' 17 | 18 | cadnano.initAppWithGui() 19 | 20 | welcome_message = """ 21 | Thank you for using Cadnano2 ({})! 22 | 23 | We invite you to support the project by citing this reference: 24 | 25 | Rapid prototyping of 3D DNA-origami shapes with caDNAno 26 | Douglas et al. Nucleic Acids Res: 37(15):5001–6 (2009) 27 | https://doi.org/10.1093/nar/gkp436 28 | 29 | Report bugs at https://github.com/douglaslab/cadnano2 (include terminal output) 30 | Contact: shawn.douglas [at] ucsf.edu 31 | """ 32 | 33 | version = version("cadnano2") 34 | 35 | def main(args=None): 36 | print(welcome_message.format(version)) 37 | app = cadnano.app() 38 | if "-p" in sys.argv: 39 | print("Collecting profile data into cadnano.profile") 40 | import cProfile 41 | cProfile.run('app.exec_()', 'cadnano.profile') 42 | print("Done collecting profile data. Use -P to print it out.") 43 | exit() 44 | elif "-P" in sys.argv: 45 | from pstats import Stats 46 | s = Stats('cadnano.profile') 47 | print("Internal Time Top 10:") 48 | s.sort_stats('cumulative').print_stats(10) 49 | print("") 50 | print("Total Time Top 10:") 51 | s.sort_stats('time').print_stats(10) 52 | exit() 53 | elif "-t" in sys.argv: 54 | print("running tests") 55 | from tests.runall import main as runTests 56 | runTests(useXMLRunner=False) 57 | exit() 58 | app.exec_() 59 | 60 | 61 | if __name__ == '__main__': 62 | sys.exit(main() or 0) -------------------------------------------------------------------------------- /cadnano2/model/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ["document", "enum", "decorators", "io", "oligo", "parts", "strand", "strands", "strandset", "virtualhelix"] -------------------------------------------------------------------------------- /cadnano2/model/decorators/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/model/decorators/__init__.py -------------------------------------------------------------------------------- /cadnano2/model/decorators/decorator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | from operator import attrgetter 5 | import cadnano2.util as util 6 | from array import array 7 | 8 | # import Qt stuff into the module namespace with PySide, PyQt4 independence 9 | util.qtWrapImport('QtCore', globals(), ['QObject', 'Qt']) 10 | util.qtWrapImport('QtGui', globals(), ['QUndoStack', 'QUndoCommand']) 11 | 12 | class Decorator(object): 13 | """ 14 | Decorators do not affect an applied sequence 15 | """ 16 | def __init__(self, index): 17 | if self.__class__ == Decorator: 18 | e = "Decorator should be subclassed." 19 | raise NotImplementedError(e) 20 | self._index = idex 21 | self._dType = None 22 | self._privateSequence = None 23 | # end def 24 | 25 | def privateLength(self): 26 | """ 27 | This is the length of a sequence that is immutable by the strand 28 | """ 29 | return length(self._privateSequence) 30 | 31 | def decoratorType(self): 32 | return self._dtype 33 | # end class -------------------------------------------------------------------------------- /cadnano2/model/decorators/insertion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | 5 | class Insertion(object): 6 | """ 7 | Insertions do affect an applied sequence and do not store a sequence 8 | themselves. They are a skip if the length is less than 0 9 | """ 10 | def __init__(self, index, length): 11 | self._length = length 12 | self._index = index 13 | # end def 14 | 15 | def length(self): 16 | """ 17 | This is the length of a sequence that is immutable by the strand 18 | """ 19 | return self._length 20 | 21 | def setLength(self, length): 22 | self._length = length 23 | # end def 24 | 25 | def updateIdx(self, delta): 26 | self._index += delta 27 | # end def 28 | 29 | def idx(self): 30 | return self._index 31 | # end def 32 | 33 | def isSkip(self): 34 | return self.length() < 0 35 | # end class -------------------------------------------------------------------------------- /cadnano2/model/decorators/modifier.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | 5 | class Modifier(object): 6 | """ 7 | Modifiers do affect an applied sequence and do not store a sequence 8 | themselves. They cause a base changed to another sequence. 9 | Modifiers DO NOT affect the length of a strand 10 | """ 11 | def __init__(self, idx): 12 | if self.__class__ == Modifier: 13 | e = "Modifier should be subclassed." 14 | raise NotImplementedError(e) 15 | self._mType = None 16 | self._lowIdx = idx 17 | self._highIdx = self._lowIdx 18 | self._privateSequence = None 19 | # end def 20 | 21 | def length(self): 22 | """ 23 | This is the length of a sequence that is immutable by the strand 24 | """ 25 | return self._highIdx - self._lowIdx + 1 26 | 27 | def modifierType(self): 28 | return self._mtype 29 | # end class -------------------------------------------------------------------------------- /cadnano2/model/enum.py: -------------------------------------------------------------------------------- 1 | 2 | class LatticeType: 3 | Honeycomb = 0 4 | Square = 1 5 | 6 | 7 | class EndType: 8 | FivePrime = 0 9 | ThreePrime = 1 10 | 11 | 12 | class StrandType: 13 | Scaffold = 0 14 | Staple = 1 15 | 16 | 17 | class Parity: 18 | Even = 0 19 | Odd = 1 20 | 21 | 22 | class BreakType: 23 | Left5Prime = 0 24 | Left3Prime = 1 25 | Right5Prime = 2 26 | Right3Prime = 3 27 | 28 | 29 | class Crossovers: 30 | honeycombScafLeft = [[1, 11], [8, 18], [4, 15]] 31 | honeycombScafRight = [[2, 12], [9, 19], [5, 16]] 32 | honeycombStapLeft = [[6], [13], [20]] 33 | honeycombStapRight = [[7], [14], [0]] 34 | squareScafLeft = [[4, 26, 15], [18, 28, 7], [10, 20, 31], [2, 12, 23]] 35 | squareScafRight = [[5, 27, 16], [19, 29, 8], [11, 21, 0], [3, 13, 24]] 36 | squareStapLeft = [[31], [23], [15], [7]] 37 | squareStapRight = [[0], [24], [16], [8]] 38 | 39 | 40 | class HandleOrient: 41 | LeftUp = 0 42 | RightUp = 1 43 | LeftDown = 2 44 | RightDown = 3 45 | -------------------------------------------------------------------------------- /cadnano2/model/io/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/model/io/__init__.py -------------------------------------------------------------------------------- /cadnano2/model/io/decoder.py: -------------------------------------------------------------------------------- 1 | import json 2 | from .legacydecoder import import_legacy_dict 3 | from cadnano2.ui.dialogs.ui_latticetype import Ui_LatticeType 4 | import cadnano2.util as util 5 | import cadnano2.cadnano as cadnano 6 | if cadnano.app().isGui(): # headless: 7 | from cadnano2.ui.dialogs.ui_latticetype import Ui_LatticeType 8 | util.qtWrapImport('QtWidgets', globals(), ['QDialog', 'QDialogButtonBox']) 9 | 10 | 11 | def decode(document, string): 12 | if cadnano.app().isGui(): 13 | # from ui.dialogs.ui_latticetype import Ui_LatticeType 14 | # util.qtWrapImport('QtGui', globals(), ['QDialog', 'QDialogButtonBox']) 15 | dialog = QDialog() 16 | dialogLT = Ui_LatticeType() # reusing this dialog, should rename 17 | dialogLT.setupUi(dialog) 18 | 19 | # try: # try to do it fast 20 | # try: 21 | # import cjson 22 | # packageObject = cjson.decode(string) 23 | # except: # fall back to if cjson not available or on decode error 24 | # packageObject = json.loads(string) 25 | # except ValueError: 26 | # dialogLT.label.setText("Error decoding JSON object.") 27 | # dialogLT.buttonBox.setStandardButtons(QDialogButtonBox.Ok) 28 | # dialog.exec() 29 | # return 30 | packageObject = json.loads(string) 31 | 32 | if packageObject.get('.format', None) != 'caDNAno2': 33 | import_legacy_dict(document, packageObject) -------------------------------------------------------------------------------- /cadnano2/model/io/encoder.py: -------------------------------------------------------------------------------- 1 | from json import dumps 2 | from .legacyencoder import legacy_dict_from_doc 3 | 4 | 5 | def encode(document, helixOrderList, io): 6 | obj = legacy_dict_from_doc(document, io.name, helixOrderList) 7 | json_string = dumps(obj, separators=(',',':')) # compact encoding 8 | io.write(json_string) 9 | -------------------------------------------------------------------------------- /cadnano2/model/io/legacyencoder.py: -------------------------------------------------------------------------------- 1 | from os.path import basename 2 | from cadnano2.model.enum import StrandType 3 | 4 | 5 | def legacy_dict_from_doc(document, fname, helixOrderList): 6 | part = document.selectedPart() 7 | numBases = part.maxBaseIdx()+1 8 | 9 | # iterate through virtualhelix list 10 | vhList = [] 11 | for row, col in helixOrderList: 12 | vh = part.virtualHelixAtCoord((row, col)) 13 | # insertions and skips 14 | insertionDict = part.insertions()[(row, col)] 15 | insts = [0 for i in range(numBases)] 16 | skips = [0 for i in range(numBases)] 17 | for idx, insertion in insertionDict.items(): 18 | if insertion.isSkip(): 19 | skips[idx] = insertion.length() 20 | else: 21 | insts[idx] = insertion.length() 22 | # colors 23 | stapColors = [] 24 | for strand in vh.stapleStrandSet(): 25 | if strand.connection5p() == None: 26 | c = str(strand.oligo().color())[1:] # drop the hash 27 | stapColors.append([strand.idx5Prime(), int(c, 16)]) 28 | scafColors = set() 29 | for strand in vh.scaffoldStrandSet(): 30 | if strand.connection5p() == None or \ 31 | (strand == strand.oligo().strand5p() and strand.oligo().isLoop()): 32 | c = str(strand.oligo().color())[1:] # drop the hash 33 | scafColors.add((strand.idx5Prime(), int(c, 16))) 34 | 35 | vhDict = {"row": row, 36 | "col": col, 37 | "num": vh.number(), 38 | "scaf": vh.getLegacyStrandSetArray(StrandType.Scaffold), 39 | "stap": vh.getLegacyStrandSetArray(StrandType.Staple), 40 | "loop": insts, 41 | "skip": skips, 42 | "scafLoop": [], 43 | "stapLoop": [], 44 | "stap_colors": stapColors, 45 | "scaf_colors": list(scafColors)} 46 | vhList.append(vhDict) 47 | bname = basename(str(fname)) 48 | obj = {"name": bname, "vstrands": vhList} 49 | return obj 50 | -------------------------------------------------------------------------------- /cadnano2/model/parts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/model/parts/__init__.py -------------------------------------------------------------------------------- /cadnano2/model/parts/honeycombpart.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | from cadnano2.cadnano import app 5 | from .part import Part 6 | from cadnano2.model.enum import LatticeType 7 | 8 | 9 | class Crossovers: 10 | honeycombScafLow = [[1, 11], [8, 18], [4, 15]] 11 | honeycombScafHigh = [[2, 12], [9, 19], [5, 16]] 12 | honeycombStapLow = [[6], [13], [20]] 13 | honeycombStapHigh = [[7], [14], [0]] 14 | 15 | 16 | root3 = 1.732051 17 | 18 | 19 | class HoneycombPart(Part): 20 | _step = 21 # 32 in square 21 | _turnsPerStep = 2.0 22 | _helicalPitch = _step/_turnsPerStep 23 | _twistPerBase = 360/_helicalPitch # degrees 24 | _twistOffset = 0 # degrees 25 | 26 | _activeBaseIndex = _step 27 | _subStepSize = _step / 3 28 | # Used in VirtualHelix::potentialCrossoverList 29 | _scafL = Crossovers.honeycombScafLow 30 | _scafH = Crossovers.honeycombScafHigh 31 | _stapL = Crossovers.honeycombStapLow 32 | _stapH = Crossovers.honeycombStapHigh 33 | 34 | def __init__(self, *args, **kwargs): 35 | super(HoneycombPart, self).__init__(self, *args, **kwargs) 36 | self._maxRow = kwargs.get('maxRow', app().prefs.honeycombRows) 37 | self._maxCol = kwargs.get('maxCol', app().prefs.honeycombCols) 38 | self._maxBase = int(kwargs.get('maxSteps', app().prefs.honeycombSteps) * self._step - 1) 39 | 40 | def crossSectionType(self): 41 | """Returns the cross-section type of the DNA part.""" 42 | return LatticeType.Honeycomb 43 | 44 | def isEvenParity(self, row, column): 45 | return (row % 2) == (column % 2) 46 | # end def 47 | 48 | def isOddParity(self, row, column): 49 | return (row % 2) ^ (column % 2) 50 | # end def 51 | 52 | def getVirtualHelixNeighbors(self, virtualHelix): 53 | """ 54 | returns the list of neighboring virtualHelices based on parity of an 55 | input virtualHelix 56 | 57 | If a potential neighbor doesn't exist, None is returned in it's place 58 | """ 59 | neighbors = [] 60 | vh = virtualHelix 61 | if vh == None: 62 | return neighbors 63 | 64 | # assign the method to a a local variable 65 | getVH = self.virtualHelixAtCoord 66 | # get the vh's row and column r,c 67 | (r, c) = vh.coord() 68 | 69 | if self.isEvenParity(r, c): 70 | neighbors.append(getVH((r,c+1))) # p0 neighbor (p0 is a direction) 71 | neighbors.append(getVH((r-1,c))) # p1 neighbor 72 | neighbors.append(getVH((r,c-1))) # p2 neighbor 73 | else: 74 | neighbors.append(getVH((r,c-1))) # p0 neighbor (p0 is a direction) 75 | neighbors.append(getVH((r+1,c))) # p1 neighbor 76 | neighbors.append(getVH((r,c+1))) # p2 neighbor 77 | # For indices of available directions, use range(0, len(neighbors)) 78 | return neighbors # Note: the order and presence of Nones is important 79 | # end def 80 | 81 | def latticeCoordToPositionXY(self, row, column, scaleFactor=1.0): 82 | """make sure self._radius is a float""" 83 | radius = self._radius 84 | x = column*radius*root3 85 | if self.isOddParity(row, column): # odd parity 86 | y = row*radius*3 + radius 87 | else: # even parity 88 | y = row*radius*3 89 | return scaleFactor*x, scaleFactor*y 90 | # end def 91 | 92 | def positionToCoord(self, x, y, scaleFactor=1.0): 93 | radius = self._radius 94 | column = int(x/(radius*root3*scaleFactor) + 0.5) 95 | 96 | rowTemp = y/(radius*scaleFactor) 97 | if (rowTemp % 3) + 0.5 > 1.0: 98 | # odd parity 99 | row = int((rowTemp-1)/3 + 0.5) 100 | else: 101 | # even parity 102 | row = int(rowTemp/3 + 0.5) 103 | # end def 104 | 105 | ########################## Archiving / Unarchiving ######################### 106 | def fillSimpleRep(self, sr): 107 | super(HoneycombPart, self).fillSimpleRep(sr) 108 | sr['.class'] = 'HoneycombPart' 109 | -------------------------------------------------------------------------------- /cadnano2/model/parts/squarepart.py: -------------------------------------------------------------------------------- 1 | from cadnano2.cadnano import app 2 | from cadnano2.model.enum import LatticeType 3 | from .part import Part 4 | 5 | 6 | class Crossovers: 7 | squareScafLow = [[4, 26, 15], [18, 28, 7], [10, 20, 31], [2, 12, 23]] 8 | squareScafHigh = [[5, 27, 16], [19, 29, 8], [11, 21, 0], [3, 13, 24]] 9 | squareStapLow = [[31], [23], [15], [7]] 10 | squareStapHigh = [[0], [24], [16], [8]] 11 | 12 | 13 | class SquarePart(Part): 14 | _step = 32 # 21 in honeycomb 15 | _subStepSize = _step / 4 16 | _turnsPerStep = 3.0 17 | _helicalPitch = _step/_turnsPerStep 18 | _twistPerBase = 360/_helicalPitch # degrees 19 | _twistOffset = 180 + _twistPerBase/2 # degrees 20 | 21 | # Used in VirtualHelix::potentialCrossoverList 22 | _scafL = Crossovers.squareScafLow 23 | _scafH = Crossovers.squareScafHigh 24 | _stapL = Crossovers.squareStapLow 25 | _stapH = Crossovers.squareStapHigh 26 | 27 | def __init__(self, *args, **kwargs): 28 | super(SquarePart, self).__init__(self, *args, **kwargs) 29 | self._maxRow = kwargs.get('maxRow', app().prefs.squareRows) 30 | self._maxCol = kwargs.get('maxCol', app().prefs.squareCols) 31 | self._maxBase = int(kwargs.get('maxSteps', app().prefs.squareSteps) * self._step - 1) 32 | 33 | def crossSectionType(self): 34 | return LatticeType.Square 35 | # end def 36 | 37 | def isEvenParity(self, row, column): 38 | return (row % 2) == (column % 2) 39 | # end def 40 | 41 | def isOddParity(self, row, column): 42 | return (row % 2) ^ (column % 2) 43 | # end def 44 | 45 | def getVirtualHelixNeighbors(self, virtualHelix): 46 | """ 47 | returns the list of neighboring virtualHelices based on parity of an 48 | input virtualHelix 49 | 50 | If a potential neighbor doesn't exist, None is returned in it's place 51 | """ 52 | neighbors = [] 53 | vh = virtualHelix 54 | if vh == None: 55 | return neighbors 56 | 57 | # assign the method to a a local variable 58 | getVH = self.virtualHelixAtCoord 59 | # get the vh's row and column r,c 60 | (r, c) = vh.coord() 61 | 62 | if self.isEvenParity(r, c): 63 | neighbors.append(getVH((r,c+1))) # p0 neighbor (p0 is a direction) 64 | neighbors.append(getVH((r+1,c))) # p1 neighbor 65 | neighbors.append(getVH((r,c-1))) # p2 neighbor 66 | neighbors.append(getVH((r-1,c))) # p2 neighbor 67 | else: 68 | neighbors.append(getVH((r,c-1))) # p0 neighbor (p0 is a direction) 69 | neighbors.append(getVH((r-1,c))) # p1 neighbor 70 | neighbors.append(getVH((r,c+1))) # p2 neighbor 71 | neighbors.append(getVH((r+1,c))) # p3 neighbor 72 | # For indices of available directions, use range(0, len(neighbors)) 73 | return neighbors # Note: the order and presence of Nones is important 74 | # end def 75 | 76 | def latticeCoordToPositionXY(self, row, column, scaleFactor=1.0): 77 | """ 78 | make sure self._radius is a float 79 | """ 80 | radius = self._radius 81 | y = row*2*radius 82 | x = column*2*radius 83 | return scaleFactor*x, scaleFactor*y 84 | # end def 85 | 86 | def positionToCoord(self, x, y, scaleFactor=1.0): 87 | """ 88 | """ 89 | radius = self._radius 90 | row = int(y/(2*radius*scaleFactor) + 0.5) 91 | column = int(x/(2*radius*scaleFactor) + 0.5) 92 | return row, column 93 | # end def 94 | 95 | def fillSimpleRep(self, sr): 96 | super(SquarePart, self).fillSimpleRep(sr) 97 | sr['.class'] = 'SquarePart' 98 | -------------------------------------------------------------------------------- /cadnano2/osx/CNApplicationDelegate.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file houses the code that allows the opening of cadnano files by dragging 3 | to the icon in the dock or double clicking on the icon. 4 | """ 5 | 6 | import objc, os 7 | from Foundation import * 8 | from AppKit import * 9 | from controllers.documentcontroller import DocumentController 10 | from cadnano2.model.io.decoder import decode 11 | from cadnano2.cadnano import app as sharedCadnanoObj 12 | 13 | 14 | class CNApplicationDelegate(NSObject): 15 | def application_openFile_(self, app, f): 16 | if f == "main.py": # ignore 17 | return 18 | extension = os.path.splitext(f)[1].lower() 19 | if extension not in ('.nno', '.json', '.cadnano'): 20 | print("Could not open file %s (bad extension %s)"%(f, extension)) 21 | return 22 | dc = list(sharedCadnanoObj().documentControllers)[0] 23 | decode(dc.document(), file(str(f)).read()) 24 | return None 25 | 26 | def application_openFiles_(self, app, fs): 27 | if fs.isKindOfClass_(NSCFString): 28 | self.application_openFile_(app, fs) 29 | return 30 | for f in fs: 31 | self.application_openFiles_(app, f) 32 | 33 | def applicationShouldTerminate_(self, app): 34 | for dc in sharedCadnanoObj().documentControllers: 35 | if not dc.maybeSave(): 36 | return NSTerminateCancel 37 | return NSTerminateNow 38 | 39 | sharedDelegate = CNApplicationDelegate.alloc().init() 40 | NSApplication.sharedApplication().setDelegate_(sharedDelegate) 41 | -------------------------------------------------------------------------------- /cadnano2/osx/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/osx/__init__.py -------------------------------------------------------------------------------- /cadnano2/plugins/autobreak/Makefile: -------------------------------------------------------------------------------- 1 | $(eval PYUIC_VERSION = -v $(shell pyuic5 -version 2> /dev/null):/output) 2 | 3 | all: autobreakconfig_ui.py 4 | 5 | autobreakconfig_ui.py : autobreakconfig.ui 6 | ifdef PYUIC_VERSION 7 | pyuic5 $< > $@ 8 | else 9 | @echo "ERROR: pyuic5 not found" 10 | endif -------------------------------------------------------------------------------- /cadnano2/plugins/autobreak/__init__.py: -------------------------------------------------------------------------------- 1 | from .autobreakconfig import AutobreakConfig 2 | import cadnano, util 3 | util.qtWrapImport('QtGui', globals(), ['QAction', 'QIcon', 'QPixmap']) 4 | 5 | 6 | class AutobreakHandler(object): 7 | def __init__(self, document, window): 8 | self.doc, self.win = document, window 9 | icon10 = QIcon() 10 | icon10.addPixmap(QPixmap(":/pathtools/autobreak"), QIcon.Mode.Normal, QIcon.State.Off) 11 | self.actionAutoBreak = QAction(window) 12 | self.actionAutoBreak.setIcon(icon10) 13 | self.actionAutoBreak.setText('AutoBreak') 14 | self.actionAutoBreak.setToolTip("Click this button to generate a default set of staples.") 15 | self.actionAutoBreak.setObjectName("actionAutoBreak") 16 | self.actionAutoBreak.triggered.connect(self.actionAutobreakSlot) 17 | self.win.menuPlugins.addAction(self.actionAutoBreak) 18 | # add to main tool bar 19 | self.win.topToolBar.insertAction(self.win.actionFiltersLabel, self.actionAutoBreak) 20 | self.win.topToolBar.insertSeparator(self.win.actionFiltersLabel) 21 | self.configDialog = None 22 | 23 | def actionAutobreakSlot(self): 24 | """Only show the dialog if staple strands exist.""" 25 | part = self.doc.controller().activePart() 26 | if part != None: # is there a part? 27 | for o in list(part.oligos()): 28 | if o.isStaple(): # is there a staple oligo? 29 | if self.configDialog == None: 30 | self.configDialog = AutobreakConfig(self.win, self) 31 | self.configDialog.show() 32 | return 33 | 34 | 35 | def documentWindowWasCreatedSlot(doc, win): 36 | doc.autobreakHandler = AutobreakHandler(doc, win) 37 | 38 | # Initialization 39 | for c in cadnano.app().documentControllers: 40 | doc, win = c.document(), c.window() 41 | doc.autobreakHandler = AutobreakHandler(doc, win) 42 | cadnano.app().documentWindowWasCreatedSignal.connect(documentWindowWasCreatedSlot) 43 | -------------------------------------------------------------------------------- /cadnano2/plugins/autobreak/autobreakconfig.py: -------------------------------------------------------------------------------- 1 | """ 2 | config 3 | Created by Jonathan deWerd on 2012-01-19. 4 | """ 5 | import cadnano2.util as util 6 | import cadnano2.cadnano as cadnano 7 | from . import autobreakconfig_ui 8 | from . import autobreak 9 | util.qtWrapImport('QtGui', globals(), ['QKeySequence']) 10 | util.qtWrapImport('QtCore', globals(), ['Qt']) 11 | util.qtWrapImport('QtWidgets', globals(), ['QDialog', 'QDialogButtonBox']) 12 | 13 | 14 | class AutobreakConfig(QDialog, autobreakconfig_ui.Ui_Dialog): 15 | def __init__(self, parent, handler): 16 | QDialog.__init__(self, parent, Qt.WindowType.Sheet) 17 | self.setupUi(self) 18 | self.handler = handler 19 | fb = self.buttonBox.button(QDialogButtonBox.Cancel) 20 | fb.setShortcut(QKeySequence(Qt.CTRL | Qt.Key.Key_R )) 21 | 22 | def keyPressEvent(self, e): 23 | return QDialog.keyPressEvent(self, e) 24 | 25 | def closeDialog(self): 26 | self.close() 27 | 28 | def accept(self): 29 | part = self.handler.doc.controller().activePart() 30 | if part != None: 31 | settings = {\ 32 | 'stapleScorer' : autobreak.tgtLengthStapleScorer,\ 33 | 'minStapleLegLen' : self.minLegLengthSpinBox.value(),\ 34 | 'minStapleLen' : self.minLengthSpinBox.value(),\ 35 | 'maxStapleLen' : self.maxLengthSpinBox.value(),\ 36 | } 37 | self.handler.win.pathGraphicsView.setViewportUpdateOn(False) 38 | # print "pre verify" 39 | # part.verifyOligos() 40 | # print "breakStaples" 41 | autobreak.breakStaples(part, settings) 42 | # print "post break verify" 43 | # part.verifyOligos() 44 | self.handler.win.pathGraphicsView.setViewportUpdateOn(True) 45 | self.close() 46 | -------------------------------------------------------------------------------- /cadnano2/plugins/test.py: -------------------------------------------------------------------------------- 1 | import cadnano 2 | print("Plugin loaded, has access to cadnano: %s"%cadnano) 3 | -------------------------------------------------------------------------------- /cadnano2/tests/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['cadnanoguitestcase'] 2 | -------------------------------------------------------------------------------- /cadnano2/tests/cadnanoguitestcase.py: -------------------------------------------------------------------------------- 1 | # from PyQt4.QtCore import * 2 | # from PyQt4.QtGui import * 3 | import cadnano 4 | import tests.guitestcase 5 | 6 | main = tests.guitestcase.main 7 | 8 | 9 | class CadnanoGuiTestCase(tests.guitestcase.GUITestCase): 10 | """ 11 | SEE: http://docs.python.org/library/unittest.html 12 | """ 13 | def setUp(self): 14 | """ 15 | The setUp method is called before running any test. It is used 16 | to set the general conditions for the tests to run correctly. 17 | For GUI Tests, you always have to call setWidget to tell the 18 | framework what you will be testing. 19 | """ 20 | import sys 21 | 22 | self.app = cadnano.initAppWithGui() # kick off a Gui style app 23 | self.documentController = list(self.app.documentControllers)[0] 24 | self.mainWindow = self.documentController.win 25 | 26 | # Include this or the automatic build will hang 27 | self.app.dontAskAndJustDiscardUnsavedChanges = True 28 | 29 | # By setting the widget to the main window we can traverse and 30 | # interact with any part of it. Also, tearDown will close 31 | # the application so we don't need to worry about that. 32 | self.setWidget(self.mainWindow, False, None) 33 | 34 | def tearDown(self): 35 | """ 36 | The tearDown method is called at the end of running each test, 37 | generally used to clean up any objects created in setUp 38 | """ 39 | tests.guitestcase.GUITestCase.tearDown(self) 40 | 41 | if __name__ == '__main__': 42 | tests.guitestcase.main() 43 | -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/tests/functionaltestinputs/__init__.py -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/gap_vs_skip.csv: -------------------------------------------------------------------------------- 1 | Start,End,Sequence,Length,Color 2 | 0[22],0[11],ACCGTC?TATCA,12,#f74308 3 | 2[22],2[11],ACCGTCTATCA,11,#03b6a2 4 | -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/gap_vs_skip.json: -------------------------------------------------------------------------------- 1 | {"name":"Wed Oct 19 2011 15:03:02 GMT-0400","vstrands":[{"stap":[[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[0,12,-1,-1],[0,13,0,11],[0,14,0,12],[0,15,0,13],[0,16,0,14],[0,17,0,15],[0,18,0,16],[0,19,0,17],[0,20,0,18],[0,21,0,19],[0,22,0,20],[-1,-1,0,21],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]],"scaf":[[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,0,12],[0,11,0,13],[0,12,0,14],[0,13,0,15],[0,14,0,17],[-1,-1,-1,-1],[0,15,0,18],[0,17,0,19],[0,18,0,20],[0,19,0,21],[0,20,0,22],[0,21,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]],"scafLoop":[],"stapLoop":[],"skip":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"row":3,"loop":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"num":0,"col":15,"stap_colors":[[22,16204552]]},{"stap":[[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[2,12,-1,-1],[2,13,2,11],[2,14,2,12],[2,15,2,13],[2,16,2,14],[2,17,2,15],[2,18,2,16],[2,19,2,17],[2,20,2,18],[2,21,2,19],[2,22,2,20],[-1,-1,2,21],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]],"scaf":[[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,2,12],[2,11,2,13],[2,12,2,14],[2,13,2,15],[2,14,2,16],[2,15,2,17],[2,16,2,18],[2,17,2,19],[2,18,2,20],[2,19,2,21],[2,20,2,22],[2,21,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]],"scafLoop":[],"stapLoop":[],"skip":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"row":3,"loop":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"num":2,"col":17,"stap_colors":[[22,243362]]}]} -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/loop_size_1.csv: -------------------------------------------------------------------------------- 1 | Start,End,Sequence,Length,Color 0[20],0[14],GTCTATCA,8,#cc0000 -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/loop_size_1.json: -------------------------------------------------------------------------------- 1 | {"vstrands":[{"stap":[[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[0,15,-1,-1],[0,16,0,14],[0,17,0,15],[0,18,0,16],[0,19,0,17],[0,20,0,18],[-1,-1,0,19],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]],"scaf":[[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,0,15],[0,14,0,16],[0,15,0,17],[0,16,0,18],[0,17,0,19],[0,18,0,20],[0,19,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]],"scafLoop":[],"stapLoop":[],"skip":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"row":11,"loop":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"num":0,"stap_colors":[[20,13369344]],"col":15}],"name":"Thu Jul 14 2011 16:17:14 GMT-0400"} -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/loops_and_skips.csv: -------------------------------------------------------------------------------- 1 | Start,End,Sequence,Length,Color 0[41],0[0],ATTAAAGAACGTGGACTCCAACGTCAAAGGGCGAAAAACCGTCTATCA,48,#cc0000 -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/loops_and_skips.json: -------------------------------------------------------------------------------- 1 | {"vstrands":[{"stap":[[0,1,-1,-1],[0,2,0,0],[0,3,0,1],[0,4,0,2],[0,5,0,3],[0,6,0,4],[0,7,0,5],[0,8,0,6],[0,9,0,7],[0,10,0,8],[0,11,0,9],[0,12,0,10],[0,13,0,11],[0,14,0,12],[0,15,0,13],[0,16,0,14],[0,17,0,15],[0,18,0,16],[0,19,0,17],[0,20,0,18],[0,21,0,19],[0,22,0,20],[0,23,0,21],[0,24,0,22],[0,25,0,23],[0,26,0,24],[0,27,0,25],[0,28,0,26],[0,29,0,27],[0,30,0,28],[0,31,0,29],[0,32,0,30],[0,33,0,31],[0,34,0,32],[0,35,0,33],[0,36,0,34],[0,37,0,35],[0,38,0,36],[0,39,0,37],[0,40,0,38],[0,41,0,39],[-1,-1,0,40]],"scaf":[[-1,-1,0,1],[0,0,0,2],[0,1,0,3],[0,2,0,4],[0,3,0,5],[0,4,0,6],[0,5,0,7],[0,6,0,8],[0,7,0,9],[0,8,0,10],[0,9,0,11],[0,10,0,12],[0,11,0,13],[0,12,0,14],[0,13,0,15],[0,14,0,16],[0,15,0,17],[0,16,0,18],[0,17,0,19],[0,18,0,20],[0,19,0,21],[0,20,0,22],[0,21,0,23],[0,22,0,24],[0,23,0,25],[0,24,0,26],[0,25,0,27],[0,26,0,28],[0,27,0,29],[0,28,0,30],[0,29,0,31],[0,30,0,32],[0,31,0,33],[0,32,0,34],[0,33,0,35],[0,34,0,36],[0,35,0,37],[0,36,0,38],[0,37,0,39],[0,38,0,40],[0,39,0,41],[0,40,-1,-1]],"scafLoop":[],"stapLoop":[],"skip":[0,0,-1,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0,-1,0,0,0,0,-1,0,0,0,0,-1,0,0,-1,0,0,0,0,-1,0,0,-1,0,0,0],"row":12,"loop":[0,0,0,0,1,0,0,0,0,0,0,2,0,0,0,0,0,0,3,0,0,0,0,0,0,4,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0],"num":0,"stap_colors":[[41,13369344]],"col":16}],"name":"Thu Jul 14 2011 16:11:51 GMT-0400"} -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/simple42.csv: -------------------------------------------------------------------------------- 1 | Start,End,Sequence,Length,Color 2 | 0[41],0[0],GAACGTGGACTCCAACGTCAAAGGGCGAAAAACCGTCTATCA,42,#cc0000 3 | -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/simple42legacy.csv: -------------------------------------------------------------------------------- 1 | Start,End,Sequence,Length,Color 0[41],0[0],GAACGTGGACTCCAACGTCAAAGGGCGAAAAACCGTCTATCA,42,#cc0000 -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/simple42legacy.json: -------------------------------------------------------------------------------- 1 | {"name":"Thu Jul 14 2011 11:29:39 GMT-0400","vstrands":[{"stap":[[0,1,-1,-1],[0,2,0,0],[0,3,0,1],[0,4,0,2],[0,5,0,3],[0,6,0,4],[0,7,0,5],[0,8,0,6],[0,9,0,7],[0,10,0,8],[0,11,0,9],[0,12,0,10],[0,13,0,11],[0,14,0,12],[0,15,0,13],[0,16,0,14],[0,17,0,15],[0,18,0,16],[0,19,0,17],[0,20,0,18],[0,21,0,19],[0,22,0,20],[0,23,0,21],[0,24,0,22],[0,25,0,23],[0,26,0,24],[0,27,0,25],[0,28,0,26],[0,29,0,27],[0,30,0,28],[0,31,0,29],[0,32,0,30],[0,33,0,31],[0,34,0,32],[0,35,0,33],[0,36,0,34],[0,37,0,35],[0,38,0,36],[0,39,0,37],[0,40,0,38],[0,41,0,39],[-1,-1,0,40]],"scaf":[[-1,-1,0,1],[0,0,0,2],[0,1,0,3],[0,2,0,4],[0,3,0,5],[0,4,0,6],[0,5,0,7],[0,6,0,8],[0,7,0,9],[0,8,0,10],[0,9,0,11],[0,10,0,12],[0,11,0,13],[0,12,0,14],[0,13,0,15],[0,14,0,16],[0,15,0,17],[0,16,0,18],[0,17,0,19],[0,18,0,20],[0,19,0,21],[0,20,0,22],[0,21,0,23],[0,22,0,24],[0,23,0,25],[0,24,0,26],[0,25,0,27],[0,26,0,28],[0,27,0,29],[0,28,0,30],[0,29,0,31],[0,30,0,32],[0,31,0,33],[0,32,0,34],[0,33,0,35],[0,34,0,36],[0,35,0,37],[0,36,0,38],[0,37,0,39],[0,38,0,40],[0,39,0,41],[0,40,-1,-1]],"scafLoop":[],"stapLoop":[],"skip":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"row":12,"stap_colors":[[41,13369344]],"loop":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"num":0,"col":16}]} -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/skip.csv: -------------------------------------------------------------------------------- 1 | Start,End,Sequence,Length,Color 0[20],0[14],CTATCA,6,#cc0000 -------------------------------------------------------------------------------- /cadnano2/tests/functionaltestinputs/skip.json: -------------------------------------------------------------------------------- 1 | {"vstrands":[{"stap":[[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[0,15,-1,-1],[0,16,0,14],[0,17,0,15],[0,18,0,16],[0,19,0,17],[0,20,0,18],[-1,-1,0,19],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]],"scaf":[[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,0,15],[0,14,0,16],[0,15,0,17],[0,16,0,18],[0,17,0,19],[0,18,0,20],[0,19,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1],[-1,-1,-1,-1]],"scafLoop":[],"stapLoop":[],"skip":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"row":11,"loop":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"num":0,"stap_colors":[[20,13369344]],"col":15}],"name":"Thu Jul 14 2011 16:42:54 GMT-0400"} -------------------------------------------------------------------------------- /cadnano2/tests/modeltests.py: -------------------------------------------------------------------------------- 1 | """ 2 | modeltests.py 3 | 4 | Created by Shawn Douglas on 2011-06-28. 5 | 6 | Instructions: copypaste the following script into TextMate's 7 | Bundles > Bundle Editor > Show Bundle Editor > Python > Run Project Unit Tests 8 | 9 | cd "$TM_PROJECT_DIRECTORY" 10 | find . -name "*tests.py" -exec "${TM_PYTHON:-python}" '{}' \;|pre 11 | 12 | """ 13 | 14 | import sys 15 | sys.path.insert(0, '.') 16 | 17 | import tests.cadnanoguitestcase 18 | from tests.cadnanoguitestcase import CadnanoGuiTestCase 19 | import time 20 | from cadnano2.model.virtualhelix import VirtualHelix 21 | from cadnano2.model.enum import StrandType 22 | 23 | 24 | class ModelTests(CadnanoGuiTestCase): 25 | """ 26 | Create new tests by adding methods to this class that begin with "test". 27 | See for more detail: http://docs.python.org/library/unittest.html 28 | 29 | Run model tests by calling "python -m tests.modeltests" from cadnano2 root 30 | directory. 31 | """ 32 | def setUp(self): 33 | """ 34 | The setUp method is called before running any test. It is used 35 | to set the general conditions for the tests to run correctly. 36 | """ 37 | CadnanoGuiTestCase.setUp(self) 38 | # Add extra model-test-specific initialization here 39 | 40 | def tearDown(self): 41 | """ 42 | The tearDown method is called at the end of running each test, 43 | generally used to clean up any objects created in setUp 44 | """ 45 | CadnanoGuiTestCase.tearDown(self) 46 | # Add model-test-specific cleanup here 47 | 48 | def testModel1(self): 49 | """docstring for testModel1""" 50 | pass 51 | 52 | 53 | if __name__ == '__main__': 54 | print("Running Model Tests") 55 | tests.cadnanoguitestcase.main() 56 | -------------------------------------------------------------------------------- /cadnano2/tests/runall.py: -------------------------------------------------------------------------------- 1 | """ 2 | runtests.py 3 | Helper file to run tests with 1 command and output the results to an XML file. 4 | Usage: From the main cadnano folder: python -m tests.runtests 5 | Created by Flo Mazzoldi on 2011-06-15. 6 | 7 | My TextMate Script: 8 | 9 | cd "$TM_PROJECT_DIRECTORY" 10 | CADNANO_RUN_PLAINTEXT_TESTS=YES CADNANO_IGNORE_ENV_VARS_EXCEPT_FOR_ME=YES python tests/runall.py | pre 11 | """ 12 | 13 | import glob 14 | import os 15 | import unittest 16 | from .xmlrunner import XMLTestRunner 17 | # from unittests import UnitTests 18 | # from modeltests import ModelTests 19 | from .functionaltests import FunctionalTests 20 | # from recordedtests.template import RecordedTests 21 | 22 | def main(useXMLRunner=True): 23 | # load hard-coded tests 24 | # unitsuite = unittest.makeSuite(UnitTests) 25 | # modelsuite = unittest.makeSuite(ModelTests) 26 | funsuite = unittest.makeSuite(FunctionalTests) 27 | 28 | # combine and run tests 29 | # alltests = unittest.TestSuite([unitsuite, modelsuite, funsuite]) 30 | alltests = unittest.TestSuite([funsuite]) 31 | if useXMLRunner: 32 | stream = file("testresults.xml", "w") 33 | runner = XMLTestRunner(stream) 34 | result = runner.run(alltests) 35 | stream.close() 36 | else: 37 | runner = unittest.TextTestRunner(verbosity=2) 38 | result = runner.run(alltests) 39 | return result 40 | 41 | 42 | if __name__ == "__main__": 43 | textRunner = os.environ.get('CADNANO_RUN_PLAINTEXT_TESTS', None) == "YES" 44 | main(not textRunner) 45 | -------------------------------------------------------------------------------- /cadnano2/tests/unittests.py: -------------------------------------------------------------------------------- 1 | """ 2 | unittests.py 3 | 4 | Created by Shawn Douglas on 2011-06-28. 5 | """ 6 | 7 | import sys, os 8 | sys.path.insert(0, '.') 9 | 10 | import time, code 11 | from PyQt4.QtCore import * 12 | from PyQt4.QtGui import * 13 | import tests.cadnanoguitestcase 14 | from tests.cadnanoguitestcase import CadnanoGuiTestCase 15 | from cadnano2.model.enum import StrandType 16 | from cadnano2.model.virtualhelix import VirtualHelix 17 | import unittest 18 | from rangeset import RangeSet, rangeIntersection 19 | import random 20 | seed = random.Random().randint(0,1<<32) 21 | enviroseed = os.environ.get('UNITTESTS_PRNG_SEED', False) 22 | if enviroseed != False: 23 | seed = int(enviroseed) 24 | del enviroseed 25 | print("Seeding tests.unittests; use setenv UNITTESTS_PRNG_SEED=%i to replay."%seed) 26 | 27 | 28 | class UnitTests(CadnanoGuiTestCase): 29 | """ 30 | Unit tests should test individual modules, and do not necessarily need 31 | to simulate user interaction. 32 | 33 | Create new tests by adding methods to this class that begin with "test". 34 | See for more detail: http://docs.python.org/library/unittest.html 35 | 36 | Run unit tests by calling "python -m test.unittests" from cadnano2 root 37 | directory. 38 | """ 39 | def setUp(self): 40 | """ 41 | The setUp method is called before running any test. It is used 42 | to set the general conditions for the tests to run correctly. 43 | """ 44 | CadnanoGuiTestCase.setUp(self) 45 | self.prng = random.Random(seed) 46 | # Add extra unit-test-specific initialization here 47 | 48 | def tearDown(self): 49 | """ 50 | The tearDown method is called at the end of running each test, 51 | generally used to clean up any objects created in setUp 52 | """ 53 | CadnanoGuiTestCase.tearDown(self) 54 | # Add unit-test-specific cleanup here 55 | 56 | def testUnit1(self): 57 | """docstring for testUnit1""" 58 | pass 59 | 60 | if __name__ == '__main__': 61 | tc = UnitTests() 62 | tc.setUp() 63 | # tc.testRangeSet_addRange_removeRange() 64 | tests.cadnanoguitestcase.main() 65 | -------------------------------------------------------------------------------- /cadnano2/ui/Makefile: -------------------------------------------------------------------------------- 1 | IMAGES = mainwindow/images/data-svg.png mainwindow/images/data-new_32.png mainwindow/images/data-open_32.png mainwindow/images/data-save_32.png mainwindow/images/part-new-honeycomb.png mainwindow/images/part-new-square.png mainwindow/images/slice-delete-last.png mainwindow/images/slice-move.png mainwindow/images/slice-renumber.png mainwindow/images/slice-edit.png mainwindow/images/slice-go-last.png mainwindow/images/slice-go-first.png mainwindow/images/add-bases.svg mainwindow/images/remove-bases.svg mainwindow/images/path-insert.png mainwindow/images/path-pen_48.png mainwindow/images/path-paint_48.png mainwindow/images/path-move.png mainwindow/images/path-skip.png mainwindow/images/path-force-xover.png mainwindow/images/path-break_48.png mainwindow/images/path-erase_32.png mainwindow/images/path-edit_32.png mainwindow/images/export-staples.png mainwindow/images/path-modify.png mainwindow/images/path-addseq.png mainwindow/images/path-autobreak.png mainwindow/images/part-filter-part.png mainwindow/images/part-filter-endpoint.png mainwindow/images/part-filter-xover.png mainwindow/images/part-filter-strand.png 2 | DIALOGIMAGES = dialogs/images/path-edit_32.png dialogs/images/path-force-xover.png dialogs/images/path-paint_48.png 3 | 4 | $(eval PYUIC_VERSION = -v $(shell pyuic6 -version 2> /dev/null):/output) 5 | # $(eval PYRCC_VERSION = -v $(shell pyrcc6 -version 2> /dev/null):/output) 6 | 7 | all: mainwindow/ui_mainwindow.py dialogs/ui_preferences.py dialogs/ui_latticetype.py dialogs/ui_addseq.py dialogs/ui_about.py dialogs/ui_warning.py 8 | 9 | # mainwindow/icons_rc.py : mainwindow/ui.mainwindow.icons.qrc $(IMAGES) 10 | # ifdef PYRCC_VERSION 11 | # pyrcc6 -o $@ $< 12 | # else 13 | # @echo "ERROR: pyrcc6 not found 1" $(PYUIC_VERSION) $(PYRCC_VERSION) 14 | # pyrcc6 -o $@ $< 15 | # endif 16 | 17 | # dialogs/dialogicons_rc.py : dialogs/ui.dialogs.dialogicons.qrc $(DIALOGIMAGES) 18 | # ifdef PYRCC_VERSION 19 | # pyrcc6 -o $@ $< 20 | # else 21 | # @echo "ERROR: pyrcc6 not found 2" $(PYUIC_VERSION) $(PYRCC_VERSION) 22 | # endif 23 | 24 | mainwindow/ui_mainwindow.py : mainwindow/mainwindow.ui 25 | ifdef PYUIC_VERSION 26 | pyuic6 $< > $@ 27 | else 28 | @echo "ERROR: pyuic6 not found" 29 | endif 30 | 31 | dialogs/ui_preferences.py : dialogs/preferences.ui 32 | ifdef PYUIC_VERSION 33 | pyuic6 $< > $@ 34 | else 35 | @echo "ERROR: pyuic6 not found" 36 | endif 37 | 38 | dialogs/ui_latticetype.py : dialogs/latticetype.ui 39 | ifdef PYUIC_VERSION 40 | pyuic6 $< > $@ 41 | else 42 | @echo "ERROR: pyuic6 not found" 43 | endif 44 | 45 | dialogs/ui_addseq.py : dialogs/addseq.ui 46 | ifdef PYUIC_VERSION 47 | pyuic6 $< > $@ 48 | else 49 | @echo "ERROR: pyuic6 not found" 50 | endif 51 | 52 | dialogs/ui_about.py : dialogs/about.ui 53 | ifdef PYUIC_VERSION 54 | pyuic6 $< > $@ 55 | else 56 | @echo "ERROR: pyuic6 not found" 57 | endif 58 | 59 | dialogs/ui_warning.py : dialogs/warning.ui 60 | ifdef PYUIC_VERSION 61 | pyuic6 $< > $@ 62 | else 63 | @echo "ERROR: pyuic6 not found" 64 | endif 65 | 66 | -------------------------------------------------------------------------------- /cadnano2/ui/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/__init__.py -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/dialogs/__init__.py -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/addseq.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AddSeqDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 500 10 | 500 11 | 12 | 13 | 14 | Choose a sequence 15 | 16 | 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 0 24 | 25 | 26 | 27 | Standard 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | true 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Qt::Horizontal 45 | 46 | 47 | 48 | 40 49 | 20 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | Qt::Horizontal 58 | 59 | 60 | 61 | 40 62 | 20 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | Custom 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | QDialogButtonBox::Apply|QDialogButtonBox::Cancel 85 | 86 | 87 | true 88 | 89 | 90 | 91 | 92 | 93 | 94 | customButtonBox 95 | tabWidget 96 | seqTextEdit 97 | 98 | 99 | 100 | 101 | customButtonBox 102 | rejected() 103 | AddSeqDialog 104 | reject() 105 | 106 | 107 | 315 108 | 485 109 | 110 | 111 | 321 112 | 243 113 | 114 | 115 | 116 | 117 | customButtonBox 118 | clicked(QAbstractButton*) 119 | AddSeqDialog 120 | accept() 121 | 122 | 123 | 68 124 | 485 125 | 126 | 127 | 80 128 | 243 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/images/cadnano2-about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/dialogs/images/cadnano2-about.png -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/images/part-honeycomb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/dialogs/images/part-honeycomb.png -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/images/part-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/dialogs/images/part-square.png -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/images/path-addseq.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/images/path-edit_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/dialogs/images/path-edit_32.png -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/images/path-force-xover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/dialogs/images/path-force-xover.png -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/images/path-paint_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/dialogs/images/path-paint_48.png -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/images/source/cadnano2-about.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/dialogs/images/source/cadnano2-about.ai -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/latticetype.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | LatticeType 4 | 5 | 6 | 7 | 0 8 | 0 9 | 215 10 | 80 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | Import 21 | 22 | 23 | false 24 | 25 | 26 | 27 | 28 | 29 | Is this a square lattice design? 30 | 31 | 32 | 33 | 34 | 35 | 36 | Qt::Horizontal 37 | 38 | 39 | QDialogButtonBox::No|QDialogButtonBox::Yes 40 | 41 | 42 | true 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | buttonBox 52 | accepted() 53 | LatticeType 54 | accept() 55 | 56 | 57 | 248 58 | 254 59 | 60 | 61 | 157 62 | 274 63 | 64 | 65 | 66 | 67 | buttonBox 68 | rejected() 69 | LatticeType 70 | reject() 71 | 72 | 73 | 316 74 | 260 75 | 76 | 77 | 286 78 | 274 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/ui.dialogs.dialogicons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/path-addseq.svg 4 | images/path-edit_32.png 5 | images/path-force-xover.png 6 | images/path-paint_48.png 7 | 8 | 9 | images/part-honeycomb.png 10 | images/part-square.png 11 | 12 | 13 | -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/ui_addseq.py: -------------------------------------------------------------------------------- 1 | # Form implementation generated from reading ui file 'dialogs/addseq.ui' 2 | # 3 | # Created by: PyQt6 UI code generator 6.1.1 4 | # 5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is 6 | # run again. Do not edit this file unless you know what you are doing. 7 | 8 | 9 | from PyQt6 import QtCore, QtGui, QtWidgets 10 | 11 | 12 | class Ui_AddSeqDialog(object): 13 | def setupUi(self, AddSeqDialog): 14 | AddSeqDialog.setObjectName("AddSeqDialog") 15 | AddSeqDialog.resize(500, 500) 16 | AddSeqDialog.setModal(True) 17 | self.dialogGridLayout = QtWidgets.QGridLayout(AddSeqDialog) 18 | self.dialogGridLayout.setObjectName("dialogGridLayout") 19 | self.tabWidget = QtWidgets.QTabWidget(AddSeqDialog) 20 | self.tabWidget.setObjectName("tabWidget") 21 | self.tabStandard = QtWidgets.QWidget() 22 | self.tabStandard.setObjectName("tabStandard") 23 | self.standardTabGridLayout = QtWidgets.QGridLayout(self.tabStandard) 24 | self.standardTabGridLayout.setObjectName("standardTabGridLayout") 25 | self.groupBox = QtWidgets.QGroupBox(self.tabStandard) 26 | self.groupBox.setTitle("") 27 | self.groupBox.setFlat(True) 28 | self.groupBox.setObjectName("groupBox") 29 | self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox) 30 | self.verticalLayout.setObjectName("verticalLayout") 31 | self.standardTabGridLayout.addWidget(self.groupBox, 0, 1, 1, 1) 32 | spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) 33 | self.standardTabGridLayout.addItem(spacerItem, 0, 2, 1, 1) 34 | spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) 35 | self.standardTabGridLayout.addItem(spacerItem1, 0, 0, 1, 1) 36 | self.tabWidget.addTab(self.tabStandard, "") 37 | self.tabCustom = QtWidgets.QWidget() 38 | self.tabCustom.setObjectName("tabCustom") 39 | self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tabCustom) 40 | self.verticalLayout_2.setObjectName("verticalLayout_2") 41 | self.seqTextEdit = QtWidgets.QTextEdit(self.tabCustom) 42 | self.seqTextEdit.setObjectName("seqTextEdit") 43 | self.verticalLayout_2.addWidget(self.seqTextEdit) 44 | self.tabWidget.addTab(self.tabCustom, "") 45 | self.dialogGridLayout.addWidget(self.tabWidget, 0, 0, 1, 1) 46 | self.customButtonBox = QtWidgets.QDialogButtonBox(AddSeqDialog) 47 | self.customButtonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Apply|QtWidgets.QDialogButtonBox.StandardButton.Cancel) 48 | self.customButtonBox.setCenterButtons(True) 49 | self.customButtonBox.setObjectName("customButtonBox") 50 | self.dialogGridLayout.addWidget(self.customButtonBox, 1, 0, 1, 1) 51 | 52 | self.retranslateUi(AddSeqDialog) 53 | self.tabWidget.setCurrentIndex(0) 54 | self.customButtonBox.rejected.connect(AddSeqDialog.reject) 55 | self.customButtonBox.clicked['QAbstractButton*'].connect(AddSeqDialog.accept) 56 | QtCore.QMetaObject.connectSlotsByName(AddSeqDialog) 57 | AddSeqDialog.setTabOrder(self.customButtonBox, self.tabWidget) 58 | AddSeqDialog.setTabOrder(self.tabWidget, self.seqTextEdit) 59 | 60 | def retranslateUi(self, AddSeqDialog): 61 | _translate = QtCore.QCoreApplication.translate 62 | AddSeqDialog.setWindowTitle(_translate("AddSeqDialog", "Choose a sequence")) 63 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabStandard), _translate("AddSeqDialog", "Standard")) 64 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabCustom), _translate("AddSeqDialog", "Custom")) 65 | -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/ui_latticetype.py: -------------------------------------------------------------------------------- 1 | # Form implementation generated from reading ui file 'dialogs/latticetype.ui' 2 | # 3 | # Created by: PyQt6 UI code generator 6.1.1 4 | # 5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is 6 | # run again. Do not edit this file unless you know what you are doing. 7 | 8 | 9 | from PyQt6 import QtCore, QtGui, QtWidgets 10 | 11 | 12 | class Ui_LatticeType(object): 13 | def setupUi(self, LatticeType): 14 | LatticeType.setObjectName("LatticeType") 15 | LatticeType.resize(215, 80) 16 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred) 17 | sizePolicy.setHorizontalStretch(0) 18 | sizePolicy.setVerticalStretch(0) 19 | sizePolicy.setHeightForWidth(LatticeType.sizePolicy().hasHeightForWidth()) 20 | LatticeType.setSizePolicy(sizePolicy) 21 | LatticeType.setSizeGripEnabled(False) 22 | self.verticalLayout = QtWidgets.QVBoxLayout(LatticeType) 23 | self.verticalLayout.setObjectName("verticalLayout") 24 | self.label = QtWidgets.QLabel(LatticeType) 25 | self.label.setObjectName("label") 26 | self.verticalLayout.addWidget(self.label) 27 | self.buttonBox = QtWidgets.QDialogButtonBox(LatticeType) 28 | self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal) 29 | self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.No|QtWidgets.QDialogButtonBox.StandardButton.Yes) 30 | self.buttonBox.setCenterButtons(True) 31 | self.buttonBox.setObjectName("buttonBox") 32 | self.verticalLayout.addWidget(self.buttonBox) 33 | 34 | self.retranslateUi(LatticeType) 35 | self.buttonBox.accepted.connect(LatticeType.accept) 36 | self.buttonBox.rejected.connect(LatticeType.reject) 37 | QtCore.QMetaObject.connectSlotsByName(LatticeType) 38 | 39 | def retranslateUi(self, LatticeType): 40 | _translate = QtCore.QCoreApplication.translate 41 | LatticeType.setWindowTitle(_translate("LatticeType", "Import")) 42 | self.label.setText(_translate("LatticeType", "Is this a square lattice design?")) 43 | -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/ui_warning.py: -------------------------------------------------------------------------------- 1 | # Form implementation generated from reading ui file 'dialogs/warning.ui' 2 | # 3 | # Created by: PyQt6 UI code generator 6.1.1 4 | # 5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is 6 | # run again. Do not edit this file unless you know what you are doing. 7 | 8 | 9 | from PyQt6 import QtCore, QtGui, QtWidgets 10 | 11 | 12 | class Ui_Warning(object): 13 | def setupUi(self, Warning, name="Warning"): 14 | Warning.setObjectName(name) 15 | Warning.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal) 16 | Warning.resize(400, 300) 17 | self.buttonBox = QtWidgets.QDialogButtonBox(Warning) 18 | self.buttonBox.setGeometry(QtCore.QRect(30, 250, 341, 32)) 19 | self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal) 20 | self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Ok) 21 | self.buttonBox.setObjectName("buttonBox") 22 | self.title = QtWidgets.QLabel(Warning) 23 | self.title.setGeometry(QtCore.QRect(20, 30, 361, 31)) 24 | font = QtGui.QFont() 25 | font.setPointSize(24) 26 | self.title.setFont(font) 27 | self.title.setObjectName("title") 28 | self.message = QtWidgets.QLabel(Warning) 29 | self.message.setGeometry(QtCore.QRect(20, 80, 361, 151)) 30 | self.message.setWordWrap(True) 31 | self.message.setObjectName("message") 32 | 33 | self.retranslateUi(Warning) 34 | self.buttonBox.accepted.connect(Warning.accept) 35 | self.buttonBox.rejected.connect(Warning.reject) 36 | QtCore.QMetaObject.connectSlotsByName(Warning) 37 | 38 | def retranslateUi(self, Warning): 39 | _translate = QtCore.QCoreApplication.translate 40 | Warning.setWindowTitle(_translate("Warning", "Dialog")) 41 | self.title.setText(_translate("Warning", "Warning")) 42 | self.message.setText(_translate("Warning", "Text here.")) 43 | -------------------------------------------------------------------------------- /cadnano2/ui/dialogs/warning.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | Warning 4 | 5 | 6 | Qt::ApplicationModal 7 | 8 | 9 | 10 | 0 11 | 0 12 | 400 13 | 300 14 | 15 | 16 | 17 | Dialog 18 | 19 | 20 | 21 | 22 | 30 23 | 250 24 | 341 25 | 32 26 | 27 | 28 | 29 | Qt::Horizontal 30 | 31 | 32 | QDialogButtonBox::Ok 33 | 34 | 35 | 36 | 37 | 38 | 20 39 | 30 40 | 361 41 | 31 42 | 43 | 44 | 45 | 46 | 24 47 | 48 | 49 | 50 | Warning 51 | 52 | 53 | 54 | 55 | 56 | 20 57 | 80 58 | 361 59 | 151 60 | 61 | 62 | 63 | Text here. 64 | 65 | 66 | true 67 | 68 | 69 | 70 | 71 | 72 | 73 | buttonBox 74 | accepted() 75 | Warning 76 | accept() 77 | 78 | 79 | 248 80 | 254 81 | 82 | 83 | 157 84 | 274 85 | 86 | 87 | 88 | 89 | buttonBox 90 | rejected() 91 | Warning 92 | reject() 93 | 94 | 95 | 316 96 | 260 97 | 98 | 99 | 286 100 | 274 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/__init__.py -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/add-bases.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 75 | 76 | -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/cadnano2-app-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/cadnano2-app-icon.ico -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/cadnano2-app-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/cadnano2-app-icon.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/cadnano2-app-icon_shelf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/cadnano2-app-icon_shelf.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/cadnano2-document-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/cadnano2-document-icon.ico -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/cadnano2-document-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/cadnano2-document-icon.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/cadnano2-icon_doc-legacy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/cadnano2-icon_doc-legacy.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/cadnano2_installer-bkg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/cadnano2_installer-bkg.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/data-export-staples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/data-export-staples.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/data-new_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/data-new_32.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/data-open_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/data-open_32.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/data-save_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/data-save_32.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/data-svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/data-svg.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/export-staples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/export-staples.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/export-staples.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/part-filter-endpoint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/part-filter-endpoint.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/part-filter-handle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/part-filter-handle.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/part-filter-part.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/part-filter-part.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/part-filter-scaf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/part-filter-scaf.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/part-filter-stap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/part-filter-stap.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/part-filter-strand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/part-filter-strand.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/part-filter-xover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/part-filter-xover.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/part-new-honeycomb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/part-new-honeycomb.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/part-new-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/part-new-square.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-addseq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-addseq.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-addseq.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-autobreak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-autobreak.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-break_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-break_48.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-edit_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-edit_32.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-erase_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-erase_32.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-erase_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-erase_48x48.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-force-xover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-force-xover.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-frame.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-insert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-insert.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-insert_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-insert_48x48.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-loop.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-loop_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-loop_48.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-modify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-modify.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-move.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-paint_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-paint_48.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-pen_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-pen_48.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-sequence.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-skip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-skip.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-skip_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-skip_48x48.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/path-staple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/path-staple.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/remove-bases.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/slice-delete-last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/slice-delete-last.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/slice-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/slice-edit.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/slice-go-first.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/slice-go-first.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/slice-go-last.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/slice-go-last.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/slice-move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/slice-move.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/slice-renumber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/slice-renumber.png -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/cadnano2-icon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/cadnano2-icon.pdf -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/part-filter-endpoint.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/part-filter-endpoint.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/part-filter-handle.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/part-filter-handle.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/part-filter-scaf.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/part-filter-scaf.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/part-filter-stap.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/part-filter-stap.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/part-filter-strand.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/part-filter-strand.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/part-filter-xover.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/part-filter-xover.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/part-new-honeycomb.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/part-new-honeycomb.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/part-new-square.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/part-new-square.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/path-addseq.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/path-addseq.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/path-break.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/path-break.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/path-frame.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/path-frame.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/path-insert.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/path-insert.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/path-loop.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/path-loop.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/path-paint.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/path-paint.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/path-sequence.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/path-sequence.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/images/source/path-skip.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/ui/mainwindow/images/source/path-skip.ai -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/svgbutton.py: -------------------------------------------------------------------------------- 1 | import cadnano2.util as util 2 | util.qtWrapImport('QtCore', globals(), ['QObject', 'pyqtSignal', 'Qt']) 3 | util.qtWrapImport('QtWidgets', globals(), ['QGraphicsObject']) 4 | util.qtWrapImport('QtSvg', globals(), ['QSvgRenderer']) 5 | 6 | 7 | class SVGButton(QGraphicsObject): 8 | def __init__(self, fname, parent=None): 9 | super(SVGButton, self).__init__(parent) 10 | self.svg = QSvgRenderer(fname) 11 | 12 | def paint(self, painter, options, widget): 13 | self.svg.render(painter, self.boundingRect()) 14 | 15 | def boundingRect(self): 16 | return self.svg.viewBoxF() 17 | 18 | clicked = pyqtSignal() 19 | def mousePressEvent(self, event): 20 | self.clicked.emit() -------------------------------------------------------------------------------- /cadnano2/ui/mainwindow/ui.mainwindow.icons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/data-svg.png 4 | images/data-new_32.png 5 | images/export-staples.png 6 | images/data-open_32.png 7 | images/data-save_32.png 8 | 9 | 10 | images/part-filter-scaf.png 11 | images/part-filter-stap.png 12 | images/part-filter-strand.png 13 | images/part-filter-handle.png 14 | images/part-filter-part.png 15 | images/part-filter-xover.png 16 | images/part-filter-endpoint.png 17 | images/part-new-honeycomb.png 18 | images/part-new-square.png 19 | 20 | 21 | images/slice-delete-last.png 22 | images/slice-move.png 23 | images/slice-renumber.png 24 | images/slice-edit.png 25 | images/slice-go-last.png 26 | images/slice-go-first.png 27 | 28 | 29 | images/path-autobreak.png 30 | images/path-modify.png 31 | images/add-bases.svg 32 | images/path-addseq.png 33 | images/remove-bases.svg 34 | images/path-insert_48x48.png 35 | images/path-frame.png 36 | images/path-paint_48.png 37 | images/path-move.png 38 | images/path-skip_48x48.png 39 | images/path-force-xover.png 40 | images/path-break_48.png 41 | images/path-edit_32.png 42 | images/path-erase_48x48.png 43 | images/path-staple.png 44 | 45 | 46 | -------------------------------------------------------------------------------- /cadnano2/views/QGraphicsScene-event-dispatching-overview.txt: -------------------------------------------------------------------------------- 1 | Here is a brief overview of the functions through which a mouse press event will descend until it finally reaches a QGraphicsItem. 2 | 3 | ----- Run loop sends a mouse press ------ 4 | bool QGraphicsScene::event(QEvent *event) //Returns true 5 | void QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) 6 | void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent) 7 | mouseEvent->ignore() 8 | cachedItemsUnderMouse = QGraphicsScenePrivate::itemsAtPosition(...) 9 | activate window, widget (modal panel can intercept) 10 | go in order through cachedItemsUnderMouse, try to setFocusItem on them 11 | foreach thru cachedItemsUnderMouse again 12 | check the item's acceptedMouseButtons, skip if required 13 | grab the mouse 14 | *** ACCEPT THE EVENT *** 15 | void QGraphicsScenePrivate::sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent) 16 | bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event) 17 | return item->sceneEvent(event) 18 | ignore retval of sendEvent 19 | *** if mouseEvent->isAccepted() return *** 20 | ungrab 21 | propagate to view 22 | 23 | ----- QGraphicsItem receives a mouse press ----- 24 | The only default event->accept()ing that goes on is for popup widget closing 25 | bool QGraphicsItem::sceneEvent(QEvent *event) 26 | void QGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event) 27 | ignore mousePressEvent retval and return true 28 | 29 | ----- Rubber Banding ----- 30 | void QGraphicsView::mouseMoveEvent(QMouseEvent *event) 31 | If dragMode is QGraphicsView::RubberBandDrag and scene interaction allowed, proceed. 32 | If rubberBanding, proceed 33 | Dirty the viewport 34 | void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, 35 | const QTransform &deviceTransform) 36 | foreach item in QGraphicsScene::items(selection rect, descending order) 37 | if (item->flags() & QGraphicsItem::ItemIsSelectable) 38 | item->setSelected(true) 39 | foreach unselectedItem 40 | item->setSelected(false) 41 | emit selectionChanged(); -------------------------------------------------------------------------------- /cadnano2/views/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/views/__init__.py -------------------------------------------------------------------------------- /cadnano2/views/pathview/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/views/pathview/__init__.py -------------------------------------------------------------------------------- /cadnano2/views/pathview/colorpanel.py: -------------------------------------------------------------------------------- 1 | from cadnano2.views import styles 2 | import cadnano2.util as util 3 | util.qtWrapImport('QtCore', globals(), ['QRectF', 'Qt']) 4 | util.qtWrapImport('QtGui', globals(), ['QBrush', 'QFont']) 5 | util.qtWrapImport('QtWidgets', globals(), ['QApplication', 6 | 'QColorDialog', 7 | 'QGraphicsItem', 8 | 'QGraphicsSimpleTextItem']) 9 | 10 | _font = QFont(styles.thefont, 12, QFont.Weight.Bold) 11 | 12 | 13 | class ColorPanel(QGraphicsItem): 14 | _scafColors = styles.scafColors 15 | _stapColors = styles.stapColors 16 | _pen = Qt.PenStyle.NoPen 17 | 18 | def __init__(self, parent=None): 19 | super(ColorPanel, self).__init__(parent) 20 | self.rect = QRectF(0, 0, 30, 30) 21 | self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIgnoresTransformations) 22 | self.colordialog = QColorDialog() 23 | # self.colordialog.setOption(QColorDialog.DontUseNativeDialog) 24 | self._scafColorIndex = 0 # init on -1, painttool will cycle to 0 25 | self._stapColorIndex = -1 # init on -1, painttool will cycle to 0 26 | self._scafColor = self._scafColors[self._scafColorIndex] 27 | self._stapColor = self._stapColors[self._stapColorIndex] 28 | self._scafBrush = QBrush(self._scafColor) 29 | self._stapBrush = QBrush(self._stapColor) 30 | self._initLabel() 31 | self.hide() 32 | 33 | def _initLabel(self): 34 | self._label = label = QGraphicsSimpleTextItem("scaf\nstap", parent=self) 35 | label.setPos(32, 0) 36 | label.setFont(_font) 37 | # label.setBrush(_labelbrush) 38 | # label.hide() 39 | 40 | def boundingRect(self): 41 | return self.rect 42 | 43 | def paint(self, painter, option, widget=None): 44 | painter.setPen(self._pen) 45 | painter.setBrush(self._scafBrush) 46 | painter.drawRect(0, 0, 30, 15) 47 | painter.setBrush(self._stapBrush) 48 | painter.drawRect(0, 15, 30, 15) 49 | 50 | def nextColor(self): 51 | if QApplication.keyboardModifiers() & Qt.KeyboardModifier.ShiftModifier: 52 | self._scafColorIndex += 1 53 | if self._scafColorIndex == len(self._scafColors): 54 | self._scafColorIndex = 0 55 | self._scafColor = self._scafColors[self._scafColorIndex] 56 | self._scafBrush.setColor(self._scafColor) 57 | else: 58 | self._stapColorIndex += 1 59 | if self._stapColorIndex == len(self._stapColors): 60 | self._stapColorIndex = 0 61 | self._stapColor = self._stapColors[self._stapColorIndex] 62 | self._stapBrush.setColor(self._stapColor) 63 | self.update() 64 | 65 | def prevColor(self): 66 | self._scafColorIndex -= 1 67 | self._stapColorIndex -= 1 68 | 69 | def color(self): 70 | return self._stapColor 71 | 72 | def scafColorName(self): 73 | return self._scafColor.name() 74 | 75 | def stapColorName(self): 76 | return self._stapColor.name() 77 | 78 | def changeScafColor(self): 79 | self.update() 80 | 81 | def changeStapColor(self): 82 | self._stapColor = self.colordialog.currentColor() 83 | self._stapBrush = QBrush(self._stapColor) 84 | self.update() 85 | 86 | def mousePressEvent(self, event): 87 | if event.pos().y() < 10: 88 | newColor = self.colordialog.getColor(self._scafColor) 89 | if newColor.isValid() and newColor.name() != self._scafColor.name(): 90 | self._scafColor = newColor 91 | self._scafBrush = QBrush(newColor) 92 | if not newColor in self._scafColors: 93 | self._scafColors.insert(self._scafColorIndex, newColor) 94 | self.update() 95 | else: 96 | newColor = self.colordialog.getColor(self._stapColor) 97 | if newColor.isValid() and newColor.name() != self._stapColor.name(): 98 | self._stapColor = newColor 99 | self._stapBrush = QBrush(newColor) 100 | if not newColor in self._stapColors: 101 | self._stapColors.insert(self._stapColorIndex, newColor) 102 | self.update() 103 | 104 | -------------------------------------------------------------------------------- /cadnano2/views/pathview/strand/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/views/pathview/strand/__init__.py -------------------------------------------------------------------------------- /cadnano2/views/pathview/strand/abstractstranditem.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | # from exceptions import NotImplementedError 5 | import cadnano2.util as util 6 | util.qtWrapImport('QtGui', globals(), ['QGraphicsPathItem']) 7 | 8 | 9 | class AbstractStrandItem(QGraphicsPathItem): 10 | def __init__(self, parent): 11 | """The parent should be a VirtualHelixItem.""" 12 | if self.__class__ == AbstractStrandItem: 13 | raise NotImplementedError("AbstractStrandItem should be subclassed.") 14 | super(AbstractStrandItem, self).__init__(parent) 15 | self._strand = None 16 | self._oligo = None 17 | 18 | ### SIGNALS ### 19 | 20 | ### SLOTS ### 21 | def oligoAppeareanceChanged(self): 22 | """docstring for oligoAppeareanceChanged""" 23 | pass 24 | 25 | def hasNewOligoSlot(self, oligo): 26 | """docstring for hasNewOligoSlot""" 27 | self._oligo = oligo 28 | # redraw 29 | 30 | def strandRemovedSlot(self, strand): 31 | """docstring for strandRemovedSlot""" 32 | pass 33 | 34 | def decoratorAddedSlot(self, decorator): 35 | """docstring for decoratorAddedSlot""" 36 | pass 37 | 38 | ### METHODS ### 39 | def connectSignals(self): 40 | self._oligo.appearanceChangedSignal.connect(self.oligoAppeareanceChanged) 41 | self._strand.strandHasNewOligoSignal.connect(self.hasNewOligoSlot) 42 | self._strand.destroyedSignal.connect(self.strandRemovedSlot) 43 | self._strand.decoratorAddedSignal.connect(self.decoratorAddedSlot) 44 | 45 | def disconnectSignals(self): 46 | self._oligo.appearanceChangedSignal.disconnect(self.oligoAppeareanceChanged) 47 | self._strand.strandHasNewOligoSignal.disconnect(self.hasNewOligoSlot) 48 | self._strand.destroyedSignal.disconnect(self.strandRemovedSlot) 49 | self._strand.decoratorAddedSignal.disconnect(self.decoratorAddedSlot) 50 | 51 | ### COMMANDS ### 52 | -------------------------------------------------------------------------------- /cadnano2/views/pathview/strand/decorators/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/views/pathview/strand/decorators/__init__.py -------------------------------------------------------------------------------- /cadnano2/views/pathview/strand/decorators/abstractdecoratoritem.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import cadnano2.util as util 5 | util.qtWrapImport('QtGui', globals(), ['QGraphicsPathItem']) 6 | 7 | 8 | class AbstractDecoratorItem(QGraphicsPathItem): 9 | def __init__(self, parent): 10 | """The parent should be a VirtualHelixItem.""" 11 | if self.__class__ == AbstractDecoratorItem: 12 | e = "AbstractDecoratorItem should be subclassed." 13 | raise NotImplementedError(e) 14 | super(AbstractDecoratorItem, self).__init__(parent) 15 | self._strand = None 16 | self._oligo = None 17 | 18 | ### SIGNALS ### 19 | 20 | ### SLOTS ### 21 | def strandResizedSlot(self): 22 | """docstring for strandResizedSlot""" 23 | pass 24 | 25 | def sequenceAddedSlot(self, oligo): 26 | """docstring for sequenceAddedSlot""" 27 | pass 28 | 29 | def decoratorRemovedSlot(self, oligo): 30 | """docstring for sequenceClearedSlot""" 31 | pass 32 | 33 | ### METHODS ### 34 | 35 | ### COMMANDS ### 36 | -------------------------------------------------------------------------------- /cadnano2/views/pathview/strand/decorators/fluorophoreitem.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import cadnano2.util as util 5 | 6 | 7 | class FluorophoreItem(AbstractDecoratorItem): 8 | def __init__(self, parent): 9 | """The parent should be a VirtualHelixItem.""" 10 | super(FluorophoreItem, self).__init__(parent) 11 | 12 | ### SIGNALS ### 13 | 14 | ### SLOTS ### 15 | 16 | ### METHODS ### 17 | 18 | ### COMMANDS ### 19 | -------------------------------------------------------------------------------- /cadnano2/views/pathview/strand/decorators/skipitem.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import cadnano2.util as util 5 | 6 | 7 | class SkipItem(AbstractDecoratorItem): 8 | def __init__(self, parent): 9 | """The parent should be a VirtualHelixItem.""" 10 | super(SkipItem, self).__init__(parent) 11 | 12 | ### SIGNALS ### 13 | 14 | ### SLOTS ### 15 | 16 | ### METHODS ### 17 | 18 | ### COMMANDS ### 19 | -------------------------------------------------------------------------------- /cadnano2/views/pathview/strand/decorators/stapleextensionitem.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | 5 | class StapleExtensionItem(AbstractDecoratorItem): 6 | def __init__(self, parent): 7 | """The parent should be a VirtualHelixItem.""" 8 | super(StapleExtensionItem, self).__init__(parent) 9 | 10 | ### SIGNALS ### 11 | 12 | ### SLOTS ### 13 | 14 | ### METHODS ### 15 | 16 | ### COMMANDS ### 17 | -------------------------------------------------------------------------------- /cadnano2/views/pathview/tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/views/pathview/tools/__init__.py -------------------------------------------------------------------------------- /cadnano2/views/pathview/tools/breaktool.py: -------------------------------------------------------------------------------- 1 | from .abstractpathtool import AbstractPathTool 2 | from cadnano2.views import styles 3 | import cadnano2.util as util 4 | util.qtWrapImport('QtCore', globals(), ['QPointF', 'QRectF', 'Qt']) 5 | util.qtWrapImport('QtGui', globals(), ['QBrush', 'QFont', 'QPainterPath', 6 | 'QPen', 'QPolygonF']) 7 | util.qtWrapImport('QtWidgets', globals(), ['QGraphicsItem']) 8 | 9 | _bw = styles.PATH_BASE_WIDTH 10 | _pen = QPen(styles.redstroke, 1) 11 | _rect = QRectF(0, 0, _bw, _bw) 12 | _pathArrowLeft = QPainterPath() 13 | _l3poly = QPolygonF() 14 | _l3poly.append(QPointF(_bw, 0)) 15 | _l3poly.append(QPointF(0.25 * _bw, 0.5 * _bw)) 16 | _l3poly.append(QPointF(_bw, _bw)) 17 | _pathArrowLeft.addPolygon(_l3poly) 18 | _pathArrowRight = QPainterPath() 19 | _r3poly = QPolygonF() # right-hand 3' arr 20 | _r3poly.append(QPointF(0, 0)) 21 | _r3poly.append(QPointF(0.75 * _bw, 0.5 * _bw)) 22 | _r3poly.append(QPointF(0, _bw)) 23 | _pathArrowRight.addPolygon(_r3poly) 24 | 25 | 26 | class BreakTool(AbstractPathTool): 27 | """ 28 | docstring for BreakTool 29 | """ 30 | def __init__(self, controller): 31 | super(BreakTool, self).__init__(controller) 32 | self._isTopStrand = True 33 | 34 | def __repr__(self): 35 | return "breakTool" # first letter should be lowercase 36 | 37 | def paint(self, painter, option, widget=None): 38 | super(BreakTool, self).paint(painter, option, widget) 39 | painter.setPen(_pen) 40 | if self._isTopStrand: 41 | painter.drawPath(self._pathArrowRight) 42 | else: 43 | painter.drawPath(self._pathArrowLeft) 44 | 45 | def setTopStrand(self, isTop): 46 | """ 47 | Called in hoverMovePathHelix to set whether breaktool is hovering 48 | over a top strand (goes 5' to 3' left to right) or bottom strand. 49 | """ 50 | self._isTopStrand = isTop 51 | 52 | def hoverMove(self, item, event, flag=None): 53 | """ 54 | flag is for the case where an item in the path also needs to 55 | implement the hover method 56 | """ 57 | self.updateLocation(item, item.mapToScene(QPointF(event.position()))) 58 | posScene = item.mapToScene(QPointF(event.position())) 59 | posItem = item.mapFromScene(posScene) 60 | self.setTopStrand(self.helixIndex(posItem)[1] == 0) 61 | newPosition = self.helixPos(posItem) 62 | if newPosition != None: 63 | self.setPos(newPosition) 64 | -------------------------------------------------------------------------------- /cadnano2/views/pathview/tools/erasetool.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from .abstractpathtool import AbstractPathTool 3 | import cadnano2.util as util 4 | util.qtWrapImport('QtCore', globals(), []) 5 | util.qtWrapImport('QtGui', globals(), []) 6 | 7 | 8 | class EraseTool(AbstractPathTool): 9 | """ 10 | docstring for EraseTool 11 | """ 12 | def __init__(self, controller): 13 | super(EraseTool, self).__init__(controller) 14 | 15 | def __repr__(self): 16 | return "eraseTool" # first letter should be lowercase -------------------------------------------------------------------------------- /cadnano2/views/pathview/tools/insertiontool.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from .abstractpathtool import AbstractPathTool 3 | import cadnano2.util as util 4 | util.qtWrapImport('QtCore', globals(), []) 5 | util.qtWrapImport('QtGui', globals(), []) 6 | 7 | 8 | class InsertionTool(AbstractPathTool): 9 | """ 10 | docstring for InsertionTool 11 | """ 12 | def __init__(self, controller): 13 | super(InsertionTool, self).__init__(controller) 14 | 15 | def __repr__(self): 16 | return "insertionTool" # first letter should be lowercase -------------------------------------------------------------------------------- /cadnano2/views/pathview/tools/painttool.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from .abstractpathtool import AbstractPathTool 3 | import cadnano2.util as util 4 | util.qtWrapImport('QtCore', globals(), []) 5 | util.qtWrapImport('QtGui', globals(), []) 6 | util.qtWrapImport('QtWidgets', globals(), ['QApplication']) 7 | 8 | 9 | class PaintTool(AbstractPathTool): 10 | """ 11 | Handles visibility and color cycling for the paint tool. 12 | """ 13 | def __init__(self, controller): 14 | super(PaintTool, self).__init__(controller) 15 | self._isMacrod = False 16 | 17 | def __repr__(self): 18 | return "paintTool" # first letter should be lowercase 19 | 20 | def setActive(self, willBeActive): 21 | """Show the ColorPicker widget when active, hide when inactive.""" 22 | if willBeActive: 23 | self._window.pathColorPanel.show() 24 | else: 25 | self._window.pathColorPanel.hide() 26 | self._window.pathColorPanel.prevColor() 27 | 28 | def widgetClicked(self): 29 | """Cycle through colors on 'p' keypress""" 30 | self._window.pathColorPanel.nextColor() 31 | 32 | def customMouseRelease(self, event): 33 | if self._isMacrod: 34 | self._isMacrod = False 35 | self._window.undoStack().endMacro() 36 | # end def 37 | 38 | def isMacrod(self): 39 | return self._isMacrod 40 | # end def 41 | 42 | def setMacrod(self): 43 | self._isMacrod = True 44 | self._window.undoStack().beginMacro("Group Paint") 45 | self._window.pathGraphicsView.addToPressList(self) 46 | # end def 47 | -------------------------------------------------------------------------------- /cadnano2/views/pathview/tools/pathtoolmanager.py: -------------------------------------------------------------------------------- 1 | import os 2 | from cadnano2.cadnano import app 3 | from .selecttool import SelectTool 4 | from .penciltool import PencilTool 5 | from .breaktool import BreakTool 6 | from .erasetool import EraseTool 7 | from .insertiontool import InsertionTool 8 | from .skiptool import SkipTool 9 | from .painttool import PaintTool 10 | from .addseqtool import AddSeqTool 11 | import cadnano2.util as util 12 | 13 | # import Qt stuff into the module namespace with PySide, PyQt4 independence 14 | util.qtWrapImport('QtCore', globals(), ['QObject', 'pyqtSignal']) 15 | util.qtWrapImport('QtGui', globals(), [ 'QActionGroup']) 16 | 17 | 18 | class PathToolManager(QObject): 19 | """ 20 | Manages the interactions between Path widgets / UI elements and the model. 21 | """ 22 | def __init__(self, win): 23 | super(PathToolManager, self).__init__() 24 | self.window = win 25 | self._activeTool = None 26 | self._activePart = None 27 | self.selectTool = SelectTool(self) 28 | self.pencilTool = PencilTool(self) 29 | self.breakTool = BreakTool(self) 30 | self.eraseTool = EraseTool(self) 31 | self.insertionTool = InsertionTool(self) 32 | self.skipTool = SkipTool(self) 33 | self.paintTool = PaintTool(self) # (self, win.pathGraphicsView.toolbar) 34 | self.addSeqTool = AddSeqTool(self) 35 | 36 | def installTool(toolName, window): 37 | toolWidget = getattr(window, 'actionPath' + toolName) 38 | lToolName = toolName[0].lower() + toolName[1:] 39 | tool = getattr(self, lToolName + 'Tool') 40 | tool.actionName = 'actionPath' + toolName 41 | 42 | def clickHandler(self): 43 | toolWidget.setChecked(True) 44 | self.setActiveTool(tool) 45 | if hasattr(tool, 'widgetClicked'): 46 | tool.widgetClicked() 47 | selectToolMethodName = 'choose' + toolName + 'Tool' 48 | setattr(self.__class__, selectToolMethodName, clickHandler) 49 | handler = getattr(self, selectToolMethodName) 50 | toolWidget.triggered.connect(handler) 51 | return toolWidget 52 | 53 | tools = ('Select', 'Pencil', 'Break', 'Erase', 'Insertion', 'Skip', 'Paint', 'AddSeq') 54 | ag = QActionGroup(win) 55 | # Call installTool on every tool 56 | list(map((lambda toolName: ag.addAction(installTool(toolName, win))), tools)) 57 | ag.setExclusive(True) 58 | # Select the preferred Startup tool 59 | startupToolName = app().prefs.getStartupToolName() 60 | getattr(self, 'choose' + startupToolName + 'Tool')() 61 | 62 | ### SIGNALS ### 63 | activeToolChangedSignal = pyqtSignal(str) 64 | 65 | ### SLOTS ### 66 | 67 | ### METHODS ### 68 | def activePart(self): 69 | return self._activePart 70 | 71 | def setActivePart(self, part): 72 | self._activePart = part 73 | 74 | def activeTool(self): 75 | return self._activeTool 76 | 77 | def setActiveTool(self, newActiveTool): 78 | if newActiveTool == self._activeTool: 79 | return 80 | if self.lastLocation(): 81 | newActiveTool.updateLocation(*self.lastLocation()) 82 | if self._activeTool: 83 | self._activeTool.setActive(False) 84 | if str(newActiveTool) == "selectTool": 85 | self.window.activateSelection(True) 86 | elif str(newActiveTool) == "paintTool": 87 | self.window.activateSelection(True) 88 | else: 89 | self.window.activateSelection(False) 90 | self._activeTool = newActiveTool 91 | self._activeTool.setActive(True) 92 | self.activeToolChangedSignal.emit(self._activeTool.actionName) 93 | 94 | def isSelectToolActive(self): 95 | if self.activeTool() == self.selectTool: 96 | return True 97 | return False 98 | 99 | def lastLocation(self): 100 | """(PathHelix, posInScene) or None, depending on where 101 | the mouse is (basically, pathHelix and position of 102 | the last event seen by the active tool)""" 103 | if self._activeTool == None: 104 | return None 105 | return self._activeTool.lastLocation() 106 | # end class 107 | -------------------------------------------------------------------------------- /cadnano2/views/pathview/tools/selecttool.py: -------------------------------------------------------------------------------- 1 | from .abstractpathtool import AbstractPathTool 2 | import cadnano2.util as util 3 | util.qtWrapImport('QtCore', globals(), []) 4 | util.qtWrapImport('QtGui', globals(), []) 5 | 6 | 7 | class SelectTool(AbstractPathTool): 8 | """ 9 | SelectTool is the default tool. It allows editing of breakpoints 10 | (by clicking and dragging) and toggling of crossovers. 11 | """ 12 | def __init__(self, controller): 13 | super(SelectTool, self).__init__(controller) 14 | 15 | def __repr__(self): 16 | return "selectTool" # first letter should be lowercase -------------------------------------------------------------------------------- /cadnano2/views/pathview/tools/skiptool.py: -------------------------------------------------------------------------------- 1 | from .abstractpathtool import AbstractPathTool 2 | import cadnano2.util as util 3 | util.qtWrapImport('QtCore', globals(), []) 4 | util.qtWrapImport('QtGui', globals(), []) 5 | 6 | 7 | class SkipTool(AbstractPathTool): 8 | """ 9 | docstring for SkipTool 10 | """ 11 | def __init__(self, controller): 12 | super(SkipTool, self).__init__(controller) 13 | 14 | def __repr__(self): 15 | return "skipTool" # first letter should be lowercase -------------------------------------------------------------------------------- /cadnano2/views/sliceview/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/views/sliceview/__init__.py -------------------------------------------------------------------------------- /cadnano2/views/sliceview/activesliceitem.py: -------------------------------------------------------------------------------- 1 | """ 2 | activeslicehandle.py 3 | Created by Shawn on 2011-02-05. 4 | """ 5 | 6 | from cadnano2.controllers.itemcontrollers.activesliceitemcontroller import ActiveSliceItemController 7 | import cadnano2.util as util 8 | 9 | # import Qt stuff into the module namespace with PySide, PyQt4 independence 10 | util.qtWrapImport('QtCore', globals(), ['QPointF', 'QRectF', 'Qt', 'QObject',\ 11 | 'pyqtSignal', 'pyqtSlot', 'QEvent']) 12 | util.qtWrapImport('QtGui', globals(), ['QBrush', 13 | 'QFont', 14 | 'QPen', 15 | 'QDrag', 16 | 'QUndoCommand']) 17 | util.qtWrapImport('QtWidgets', globals(), ['QGraphicsItem', 18 | 'QGraphicsRectItem', 19 | 'QGraphicsSimpleTextItem']) 20 | 21 | 22 | class ActiveSliceItem(QGraphicsRectItem): 23 | """ActiveSliceItem for the Slice View""" 24 | def __init__(self, partItem, activeBaseIndex): 25 | super(ActiveSliceItem, self).__init__(partItem) 26 | self._partItem = partItem 27 | self._controller = ActiveSliceItemController(self, partItem.part()) 28 | self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemHasNoContents) 29 | # end def 30 | 31 | ### SLOTS ### 32 | def strandChangedSlot(self, sender, vh): 33 | if vh == None: 34 | return 35 | partItem = self._partItem 36 | vhi = partItem.getVirtualHelixItemByCoord(*vh.coord()) 37 | activeBaseIdx = partItem.part().activeBaseIndex() 38 | isActiveNow = vh.hasStrandAtIdx(activeBaseIdx) 39 | vhi.setActiveSliceView(isActiveNow, activeBaseIdx) 40 | # end def 41 | 42 | def updateIndexSlot(self, sender, newActiveSliceZIndex): 43 | part = self.part() 44 | if part.numberOfVirtualHelices() == 0: 45 | return 46 | newlyActiveVHs = set() 47 | activeBaseIdx = part.activeBaseIndex() 48 | for vhi in self._partItem._virtualHelixHash.values(): 49 | vh = vhi.virtualHelix() 50 | if vh: 51 | isActiveNow = vh.hasStrandAtIdx(activeBaseIdx) 52 | vhi.setActiveSliceView(isActiveNow, activeBaseIdx) 53 | # end def 54 | 55 | def updateRectSlot(self, part): 56 | pass 57 | # end def 58 | 59 | ### ACCESSORS ### 60 | def part(self): 61 | return self._partItem.part() 62 | # end def 63 | 64 | ### PUBLIC METHODS FOR DRAWING / LAYOUT ### 65 | def removed(self): 66 | self._partItem = None 67 | self._controller.disconnectSignals() 68 | self.controller = None 69 | # end def 70 | -------------------------------------------------------------------------------- /cadnano2/views/sliceview/slicerootitem.py: -------------------------------------------------------------------------------- 1 | from cadnano2.controllers.viewrootcontroller import ViewRootController 2 | from .partitem import PartItem 3 | import cadnano2.util as util 4 | util.qtWrapImport('QtCore', globals(), ['pyqtSignal', 'QObject']) 5 | util.qtWrapImport('QtWidgets', globals(), ['QGraphicsRectItem']) 6 | 7 | 8 | class SliceRootItem(QGraphicsRectItem): 9 | """ 10 | PathRootItem is the root item in the PathView. It gets added directly 11 | to the pathscene by DocumentWindow. It receives two signals 12 | (partAddedSignal and selectedPartChangedSignal) via its ViewRootController. 13 | 14 | PathRootItem must instantiate its own controller to receive signals 15 | from the model. 16 | """ 17 | def __init__(self, rect, parent, window, document): 18 | super(SliceRootItem, self).__init__(rect, parent) 19 | self._window = window 20 | self._document = document 21 | self._controller = ViewRootController(self, document) 22 | self._instanceItems = {} 23 | 24 | ### SIGNALS ### 25 | 26 | ### SLOTS ### 27 | def partAddedSlot(self, sender, modelPart): 28 | """ 29 | Receives notification from the model that a part has been added. 30 | Views that subclass AbstractView should override this method. 31 | """ 32 | self._modelPart = modelPart 33 | partItem = PartItem(modelPart, parent=self) 34 | self._instanceItems[partItem] = partItem 35 | self.setModifyState(self._window.actionModify.isChecked()) 36 | # end def 37 | 38 | def selectedChangedSlot(self, itemDict): 39 | """docstring for selectedChangedSlot""" 40 | pass 41 | # end def 42 | 43 | def selectionFilterChangedSlot(self, filterNameList): 44 | pass 45 | # end def 46 | 47 | def clearSelectionsSlot(self, doc): 48 | self.scene().views()[0].clearSelectionLockAndCallbacks() 49 | # end def 50 | 51 | def resetRootItemSlot(self, doc): 52 | pass 53 | # end def 54 | 55 | ### ACCESSORS ### 56 | def sliceToolManager(self): 57 | """docstring for sliceToolManager""" 58 | return self._window.sliceToolManager 59 | # end def 60 | 61 | def window(self): 62 | return self._window 63 | # end def 64 | 65 | ### METHODS ### 66 | def removePartItem(self, partItem): 67 | del self._instanceItems[partItem] 68 | # end def 69 | 70 | def resetDocumentAndController(self, document): 71 | """docstring for resetDocumentAndController""" 72 | self._document = document 73 | self._controller = ViewRootController(self, document) 74 | if len(self._instanceItems) > 0: 75 | raise ImportError 76 | # end def 77 | 78 | def setModifyState(self, bool): 79 | """docstring for setModifyState""" 80 | for partItem in self._instanceItems: 81 | partItem.setModifyState(bool) 82 | # end def 83 | -------------------------------------------------------------------------------- /cadnano2/views/sliceview/tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/views/sliceview/tools/__init__.py -------------------------------------------------------------------------------- /cadnano2/views/sliceview/tools/slicetoolmanager.py: -------------------------------------------------------------------------------- 1 | import cadnano2.util as util 2 | # import Qt stuff into the module namespace with PySide, PyQt4 independence 3 | util.qtWrapImport('QtCore', globals(), ['pyqtSignal', 'QObject']) 4 | util.qtWrapImport('QtGui', globals(), [ 'QActionGroup']) 5 | 6 | 7 | class SliceToolManager(QObject): 8 | """Manages interactions between the slice widgets/UI and the model.""" 9 | def __init__(self, win): 10 | """ 11 | We store mainWindow because a controller's got to have 12 | references to both the layer above (UI) and the layer below (model) 13 | """ 14 | super(SliceToolManager, self).__init__() 15 | self._window = win 16 | self._connectWindowSignalsToSelf() 17 | 18 | ### SIGNALS ### 19 | activeSliceSetToFirstIndexSignal = pyqtSignal() 20 | activeSliceSetToLastIndexSignal = pyqtSignal() 21 | activePartRenumber = pyqtSignal() 22 | 23 | ### SLOTS ### 24 | def activeSliceFirstSlot(self): 25 | """ 26 | Use a signal to notify the ActiveSliceHandle to move. A signal is used 27 | because the SliceToolManager must be instantiated first, and the 28 | ActiveSliceHandle can later subscribe. 29 | """ 30 | part = self._window.selectedPart() 31 | if part != None: 32 | part.setActiveBaseIndex(0) 33 | 34 | def activeSliceLastSlot(self): 35 | part = self._window.selectedPart() 36 | if part != None: 37 | part.setActiveBaseIndex(part.maxBaseIdx()-1) 38 | 39 | ### METHODS ### 40 | def _connectWindowSignalsToSelf(self): 41 | """This method serves to group all the signal & slot connections 42 | made by SliceToolManager""" 43 | self._window.actionSliceFirst.triggered.connect(self.activeSliceFirstSlot) 44 | self._window.actionSliceLast.triggered.connect(self.activeSliceLastSlot) 45 | -------------------------------------------------------------------------------- /cadnano2/views/solidview/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/cadnano2/views/solidview/__init__.py -------------------------------------------------------------------------------- /cadnano2/views/solidview/mayaUI.py: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # 3 | # Copyright 2011 Autodesk, Inc. All rights reserved. 4 | # 5 | # The MIT License 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | # this software and associated documentation files (the "Software"), to deal in 9 | # the Software without restriction, including without limitation the rights to 10 | # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11 | # of the Software, and to permit persons to whom the Software is furnished to do 12 | # so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | ############################################################################### 26 | 27 | 28 | import maya.cmds as cmds 29 | import maya.mel as mel 30 | 31 | # Original States 32 | hiddenElements = [] 33 | elementsToHide = ["toolBar", "dockControl"] 34 | mainMenuBarVisible = None 35 | gridVisible = None 36 | 37 | modelEditors = [] 38 | backgroundColors = [] 39 | """ 40 | Hideable Stuff: 41 | UIElements 42 | Grid 43 | MainMenuBar 44 | """ 45 | 46 | def simplifyUI(): 47 | hideUIElements() 48 | hideMainMenuBar() 49 | hideGrid() 50 | #mel.eval("toggleModelEditorBarsInAllPanels 0;") 51 | 52 | def restoreUI(): 53 | restoreUIElements() 54 | restoreMainMenuBar() 55 | restoreGrid() 56 | #mel.eval("toggleModelEditorBarsInAllPanels 1;") 57 | 58 | def setViewportQuality(): 59 | global modelEditors 60 | global backgroundColors 61 | backgroundColors.append(cmds.displayRGBColor('background',q=True)) 62 | backgroundColors.append(cmds.displayRGBColor('backgroundTop',q=True)) 63 | backgroundColors.append(cmds.displayRGBColor('backgroundBottom',q=True)) 64 | cmds.displayRGBColor('background', 1, 1, 1) 65 | cmds.displayRGBColor('backgroundTop', 0.762112, 0.87892, 1) 66 | cmds.displayRGBColor('backgroundBottom', 1, 1, 1) 67 | 68 | for i in cmds.lsUI(panels=True): 69 | if cmds.modelEditor(i, query=True, exists=True): 70 | sts = cmds.modelEditor(i, query=True, stateString=True) 71 | sts = sts.replace("$editorName", i) 72 | modelEditors.append(sts) 73 | cmds.modelEditor(i, edit=True, displayAppearance="smoothShaded", lineWidth=2) 74 | #, rendererName="hwRender_OpenGL_Renderer") 75 | 76 | def restoreViewportQuality(): 77 | global modelEditors 78 | global backgroundColors 79 | bc = backgroundColors 80 | cmds.displayRGBColor('background', bc[0][0], bc[0][1], bc[0][2]) 81 | cmds.displayRGBColor('backgroundTop', bc[1][0], bc[1][1], bc[1][2]) 82 | cmds.displayRGBColor('backgroundBottom', bc[2][0], bc[2][1], bc[2][2]) 83 | 84 | for e in modelEditors: 85 | mel.eval(e) 86 | 87 | def hideMainMenuBar(): 88 | global mainMenuBarVisible 89 | mainMenuBarVisible = cmds.optionVar(q="mainWindowMenubarVis") 90 | #mel.eval("setMainMenubarVisible 0;") 91 | 92 | def restoreMainMenuBar(): 93 | global mainMenuBarVisible 94 | #mel.eval("setMainMenubarVisible " + str(mainMenuBarVisible) + ";") 95 | 96 | def hideUIElements(): 97 | global hiddenElements 98 | global elementsToHide 99 | for i in cmds.lsUI(ctl=True): 100 | for e in elementsToHide: 101 | if i.find(e) != -1 and cmds.control(i, q=True, visible=True): 102 | hiddenElements.append(i) 103 | #print "hiding... " + i 104 | cmds.control(i, e=True, visible=False) 105 | break 106 | 107 | def restoreUIElements(): 108 | global hiddenElements 109 | for e in hiddenElements: 110 | #print "restoring... " + e 111 | cmds.control(e, e=True, visible=True) 112 | hiddenElements = [] 113 | 114 | def hideGrid(): 115 | global gridVisible 116 | gridVisible = cmds.optionVar(q="showGrid") 117 | cmds.grid(toggle=0) 118 | 119 | def restoreGrid(): 120 | global gridVisible 121 | cmds.grid(toggle=gridVisible) 122 | -------------------------------------------------------------------------------- /dist/cadnano2-2.4.0-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/dist/cadnano2-2.4.0-py3-none-any.whl -------------------------------------------------------------------------------- /dist/cadnano2-2.4.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/douglaslab/cadnano2/239ecc851407b64b44a8a4bdecdd5eb4848868f5/dist/cadnano2-2.4.0.tar.gz -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "cadnano2" 7 | version = "2.4.13" 8 | description = "Cadnano2 for PyQt6" 9 | authors = [ 10 | {name = "Shawn Douglas", email = "shawn.douglas@ucsf.edu"}, 11 | ] 12 | readme = "README.md" 13 | license = {text = "MIT"} 14 | requires-python = ">=3.8" 15 | dependencies = [ 16 | "PyQt6", 17 | ] 18 | classifiers = [ 19 | "Development Status :: 4 - Beta", 20 | "Intended Audience :: Science/Research", 21 | "License :: OSI Approved :: MIT License", 22 | "Operating System :: OS Independent", 23 | "Programming Language :: Python :: 3", 24 | ] 25 | 26 | [project.scripts] 27 | cadnano2 = "cadnano2.main:main" 28 | 29 | [tool.setuptools] 30 | packages = ["cadnano2"] 31 | package-data = {"cadnano2" = ["ui/mainwindow/images/*.svg", "ui/mainwindow/images/*.png"]} --------------------------------------------------------------------------------