Skip to content

Commit bed7c08

Browse files
authored
Initial commit
0 parents  commit bed7c08

18 files changed

Lines changed: 1060 additions & 0 deletions

File tree

.github/workflows/build.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Run gradle build
2+
3+
on:
4+
push:
5+
branches:
6+
- "main"
7+
pull_request:
8+
branches:
9+
- "main"
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
build:
17+
uses: qupath/actions/.github/workflows/gradle.yml@main
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name: Make draft release
2+
3+
on:
4+
workflow_dispatch:
5+
6+
jobs:
7+
build:
8+
permissions:
9+
contents: write
10+
uses: qupath/actions/.github/workflows/github-release.yml@main
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Publish release to SciJava Maven
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
release:
7+
type: boolean
8+
description: Should this be a release? (if not, do a snapshot)
9+
required: true
10+
11+
jobs:
12+
build:
13+
name: Publish release
14+
uses: qupath/actions/.github/workflows/scijava-maven.yml@main
15+
secrets: inherit
16+
with:
17+
release: ${{ inputs.release }}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Update gradle version
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
gradle-version:
7+
description: Gradle version
8+
default: latest
9+
type: string
10+
required: false
11+
12+
jobs:
13+
update:
14+
env:
15+
GH_TOKEN: ${{ github.token }}
16+
runs-on: ubuntu-latest
17+
defaults:
18+
run:
19+
shell: bash
20+
steps:
21+
- uses: actions/checkout@v4
22+
- name: Update gradlew
23+
run: |
24+
./gradlew wrapper --gradle-version ${{ inputs.gradle-version }}
25+
- name: Commit and push
26+
run: |
27+
git config user.name "github-actions[bot]"
28+
git config user.email "github-actions[bot]@users.noreply.github.com"
29+
git checkout -b gradle-update
30+
git add .
31+
git commit --allow-empty -m "Update gradle via qupath/actions/.github/workflows/update-gradle.yml"
32+
git push -u origin gradle-update
33+
gh pr create --title "Update gradle via actions" --body "$(./gradlew --version)"

.gitignore

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Javadocs
2+
docs/
3+
4+
# Maven
5+
deploy/
6+
target/
7+
log/
8+
9+
# IntelliJ
10+
.idea/
11+
*.iml
12+
out/
13+
14+
# Gradle
15+
# Use local properties (e.g. to set a specific JDK)
16+
gradle.properties
17+
build/
18+
.gradle/
19+
gradle.properties
20+
21+
# Eclipse
22+
.settings/
23+
.project
24+
.classpath
25+
26+
# VSCode
27+
.vscode/
28+
29+
# Mac
30+
.DS_Store
31+
32+
# Java
33+
hs_err*.log
34+
35+
# Other
36+
*.tmp
37+
*.bak
38+
*.swp
39+
*~.nib
40+
*thumbs.db
41+
bin/

README.md

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
# QuPath extension template
2+
3+
This repo contains a template and instructions to help create a new extension for [QuPath](https://qupath.github.io).
4+
5+
It already contains two minimal extensions - one using Java, one using Groovy - so the first task is to make sure that they work.
6+
Then, it's a matter of customizing the code to make it more useful.
7+
8+
> **Update!**
9+
> For QuPath v0.6.0 this repo switched to use Kotlin DSL for Gradle build files -
10+
> and also to use the [QuPath Gradle Plugin](https://github.com/qupath/qupath-gradle-plugin).
11+
>
12+
> The outcome is that the build files are _much_ simpler.
13+
14+
15+
## Build the extension
16+
17+
Building the extension with Gradle should be pretty easy - you don't even need to install Gradle separately, because the
18+
[Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html) will take care of that.
19+
20+
Open a command prompt, navigate to where the code lives, and use
21+
```bash
22+
gradlew build
23+
```
24+
25+
The built extension should be found inside `build/libs`.
26+
You can drag this onto QuPath to install it.
27+
You'll be prompted to create a user directory if you don't already have one.
28+
29+
The minimal extension here doesn't do much, but it should at least install a new command under the 'Extensions' menu in
30+
QuPath.
31+
32+
> In case your extension contains external dependencies beyond what QuPath already includes, you can create a
33+
> [single jar file](https://imperceptiblethoughts.com/shadow/introduction/#benefits-of-shadow) that bundles these along
34+
> with your extension by using
35+
> ```bash
36+
> gradlew shadowJar
37+
> ```
38+
> If you don't do that, you'll need to drag *all* the extra dependences onto QuPath to install them as well.
39+
40+
41+
## Configure the extension
42+
43+
Edit `settings.gradle.kts` to specify which version of QuPath your extension should be compatible with, e.g.
44+
45+
```kotlin
46+
qupath {
47+
version = "0.6.0"
48+
}
49+
```
50+
51+
Edit `build.gradle.kts` to specify the details of your extension
52+
53+
```kotlin
54+
qupathExtension {
55+
name = "qupath-extension-template"
56+
group = "io.github.qupath"
57+
version = "0.1.0-SNAPSHOT"
58+
description = "A simple QuPath extension"
59+
automaticModule = "io.github.qupath.extension.template"
60+
}
61+
```
62+
63+
64+
## Run QuPath + the extension
65+
66+
During development, your probably want to run QuPath easily with your extension installed for debugging.
67+
68+
### 0. Make sure you have Java installed
69+
You'll need to install Java first.
70+
71+
At the time of writing, we use a Java 21 JDK downloaded from https://adoptium.net/
72+
73+
> Java 21 is a 'Long Term Support' release - which is why we use it instead of the very latest version.
74+
75+
### 1. Get QuPath's source code
76+
You can find instructions at https://qupath.readthedocs.io/en/stable/docs/reference/building.html
77+
78+
### 2. Create an `include-extra` file
79+
Create a file called `include-extra` in the root directory of the QuPath source code (*not* the extension code!).
80+
81+
Set the contents of this file to:
82+
```
83+
[includeBuild]
84+
/path/to/your/extension
85+
86+
[dependencies]
87+
extension-group:extension-name
88+
```
89+
replacing the default lines where needed.
90+
91+
For example, to build the extension with the names given above you'd use
92+
```
93+
[includeBuild]
94+
../qupath-extension-template
95+
96+
[dependencies]
97+
io.github.qupath:qupath-extension-template
98+
```
99+
100+
### 3. Run QuPath
101+
Run QuPath from the command line using
102+
```
103+
gradlew run
104+
```
105+
If all goes well, QuPath should launch and you can check the *Extensions* mention to confirm the extension is installed.
106+
107+
108+
## Set up in an IDE (optional)
109+
110+
During development, things are likely to be much easier if you work within an IDE.
111+
112+
QuPath itself is developed using IntelliJ, and you can import the extension template there.
113+
114+
The setup process is as above, and you'll need a a [Run configuration](https://www.jetbrains.com/help/idea/run-debug-configuration.html)
115+
to call `gradlew run`.
116+
117+
118+
## Customize the extension
119+
120+
Now you're ready for the creative part.
121+
122+
You can develop the extension using either Java or Groovy - the template includes examples of both.
123+
124+
### Create the extension Java or Groovy file(s)
125+
126+
For the extension to work, you need to create at least one file that extends `qupath.lib.gui.extensions.QuPathExtension`.
127+
128+
There are two examples in the template, in two languages:
129+
* **Java:** `qupath.ext.template.DemoExtension.java`.
130+
* **Groovy:** `qupath.ext.template.DemoGroovyExtension.java`.
131+
132+
You can pick the one that corresponds to the language you want to use, and delete the other.
133+
134+
Then take your chosen file and rename it, edit it, move it to another package... basically, make it your own.
135+
136+
> Please **don't neglect this step!**
137+
> If you do, there's a chance of multiple extensions being created with the same class names... and causing confusion later.
138+
139+
### Update the `META-INF/services` file
140+
141+
For QuPath to *find* the extension later, the full class name needs to be available in `resources/META-INFO/services/qupath.lib.gui.extensions.QuPathExtensions`.
142+
143+
So remember to edit that file to include the class name that you actually used for your extension.
144+
145+
### Specify your license
146+
147+
Add a license file to your GitHub repo so that others know what they can and can't do with your extension.
148+
149+
This should be compatible with QuPath's license -- see https://github.com/qupath/qupath
150+
151+
## Repository configuration
152+
153+
### Easy install
154+
155+
If you follow some conventions in naming your extension and making releases, then other QuPath users will find it easy to automatically
156+
install and update your extension!
157+
158+
First, we suggest you name your extension `qupath-extension-[something]`, and keep it in its own repository (named the same as the extension),
159+
separate from other projects.
160+
161+
Next, when you want to publish a new version of your extension, use the `github_release.yml` workflow included in this repository.
162+
163+
To do so, you'd need to navigate to `Actions -> Make draft release -> Run workflow -> Run workflow` as shown in the following screenshot:
164+
165+
![Screenshot from 2024-03-14 18-44-42](https://github.com/alanocallaghan/qupath-extension-template/assets/10779688/4712a209-eda7-4f80-8bed-bbab20e4f50a)
166+
167+
This will automatically build the extension, and create a draft release containing the extension jar (and its associated sources and javadoc).
168+
You can then navigate to `Releases` and fill out information about the release --- the version, any significant changes, etc.
169+
Once published, users will be able to automatically install the extension as described here:
170+
https://qupath.readthedocs.io/en/0.5/docs/intro/extensions.html#installing-extensions
171+
172+
### Catalogs
173+
174+
QuPath's extension manager can easily install an extension if it is referenced in a **catalog**.
175+
A catalog is a JSON file hosted on a GitHub repository containing information about extensions, making it possible to easily manage them from QuPath.
176+
177+
To create a catalog, follow the [extension catalog model documentation](https://qupath.github.io/extension-catalog-model/).
178+
You will need to create a JSON file containing specific information about your extension and host it on a dedicated GitHub repository.
179+
Once the catalog is created, any user will be able to easily install your catalog by:
180+
181+
* Opening QuPath's extension manager by clicking on `Extensions` -> `Manage extensions` in QuPath.
182+
* Adding the URL to your catalog by clicking on `Manage extension catalogs` -> `Add` in the extension manager.
183+
* Clicking on the `+` symbol next to your extension in the extension manager.
184+
185+
QuPath will then make it easy to manage your extension and automatically inform users when an update is available.
186+
187+
### Replace this readme
188+
189+
Don't forget to replace the contents of this readme with your own!
190+
191+
192+
## Getting help
193+
194+
For questions about QuPath and/or creating new extensions, please use the forum at https://forum.image.sc/tag/qupath
195+
196+
------
197+
198+
## License
199+
200+
This is just a template, you're free to use it however you like.
201+
You can treat the contents of *this repository only* as being under [the Unlicense](https://unlicense.org) (except for the Gradle wrapper, which has its own license included).
202+
203+
If you use it to create a new QuPath extension, I'd strongly encourage you to select a suitable open-source license for the extension.
204+
205+
Note that *QuPath itself* is available under the GPL, so you do have to abide by those terms: see https://github.com/qupath/qupath for more.

build.gradle.kts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
plugins {
2+
// Support writing the extension in Groovy (remove this if you don't want to)
3+
groovy
4+
// To optionally create a shadow/fat jar that bundle up any non-core dependencies
5+
id("com.gradleup.shadow") version "8.3.5"
6+
// QuPath Gradle extension convention plugin
7+
id("qupath-conventions")
8+
}
9+
10+
// TODO: Configure your extension here (please change the defaults!)
11+
qupathExtension {
12+
name = "qupath-extension-template"
13+
group = "io.github.qupath"
14+
version = "0.1.0-SNAPSHOT"
15+
description = "A simple QuPath extension"
16+
automaticModule = "io.github.qupath.extension.template"
17+
}
18+
19+
// TODO: Define your dependencies here
20+
dependencies {
21+
22+
// Main dependencies for most QuPath extensions
23+
shadow(libs.bundles.qupath)
24+
shadow(libs.bundles.logging)
25+
shadow(libs.qupath.fxtras)
26+
27+
// If you aren't using Groovy, this can be removed
28+
shadow(libs.bundles.groovy)
29+
30+
// For testing
31+
testImplementation(libs.bundles.qupath)
32+
testImplementation(libs.junit)
33+
34+
}

gradle/wrapper/gradle-wrapper.jar

42.6 KB
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
4+
networkTimeout=10000
5+
validateDistributionUrl=true
6+
zipStoreBase=GRADLE_USER_HOME
7+
zipStorePath=wrapper/dists

0 commit comments

Comments
 (0)