Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions WPILibInstaller-Avalonia/Interfaces/IConfigurationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public interface IConfigurationProvider

ElasticConfig ElasticConfig { get; }

QDashConfig QDashConfig { get; }

VsCodeConfig VsCodeConfig { get; }

string InstallDirectory { get; }
Expand Down
14 changes: 14 additions & 0 deletions WPILibInstaller-Avalonia/Models/QDashConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#nullable disable

using Newtonsoft.Json;

namespace WPILibInstaller.Models
{
public class QDashConfig
{
[JsonProperty("zipFile")]
public string ZipFile { get; set; }
[JsonProperty("folder")]
public string Folder { get; set; }
}
}
4 changes: 4 additions & 0 deletions WPILibInstaller-Avalonia/ViewModels/InstallPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ await ExtractArchive(token, new[] {
configurationProvider.UpgradeConfig.Tools.Folder + "/",
configurationProvider.AdvantageScopeConfig.Folder + "/",
configurationProvider.ElasticConfig.Folder + "/",
configurationProvider.QDashConfig.Folder + "/",
"installUtils/", "icons"});
}

Expand Down Expand Up @@ -955,6 +956,7 @@ private async Task RunShortcutCreator(CancellationToken token)
shortcutData.DesktopShortcuts.Add(new ShortcutInfo(Path.Join(frcHomePath, "tools", "wpical.exe"), $"{frcYear} WPILib Tools/WPIcal {frcYear}", $"WPIcal {frcYear}", ""));
shortcutData.DesktopShortcuts.Add(new ShortcutInfo(Path.Join(frcHomePath, "advantagescope", "AdvantageScope (WPILib).exe"), $"{frcYear} WPILib Tools/AdvantageScope (WPILib) {frcYear}", $"AdvantageScope (WPILib) {frcYear}", ""));
shortcutData.DesktopShortcuts.Add(new ShortcutInfo(Path.Join(frcHomePath, "elastic", "elastic_dashboard.exe"), $"{frcYear} WPILib Tools/Elastic (WPILib) {frcYear}", $"Elastic (WPILib) {frcYear}", ""));
shortcutData.DesktopShortcuts.Add(new ShortcutInfo(Path.Join(frcHomePath, "qdash", "QDash (WPILib).exe"), $"{frcYear} WPILib Tools/QDash (WPILib) {frcYear}", $"QDash (WPILib) {frcYear}", ""));

shortcutData.StartMenuShortcuts.Add(new ShortcutInfo(Path.Join(frcHomePath, "tools", "glass.exe"), $"Programs/{frcYear} WPILib Tools/Glass {frcYear}", $"Glass {frcYear}", ""));
shortcutData.StartMenuShortcuts.Add(new ShortcutInfo(Path.Join(frcHomePath, "tools", "outlineviewer.exe"), $"Programs/{frcYear} WPILib Tools/OutlineViewer {frcYear}", $"OutlineViewer {frcYear}", ""));
Expand All @@ -968,6 +970,7 @@ private async Task RunShortcutCreator(CancellationToken token)
shortcutData.StartMenuShortcuts.Add(new ShortcutInfo(Path.Join(frcHomePath, "tools", "wpical.exe"), $"Programs/{frcYear} WPILib Tools/WPIcal {frcYear}", $"WPIcal {frcYear}", ""));
shortcutData.StartMenuShortcuts.Add(new ShortcutInfo(Path.Join(frcHomePath, "advantagescope", "AdvantageScope (WPILib).exe"), $"Programs/{frcYear} WPILib Tools/AdvantageScope (WPILib) {frcYear}", $"AdvantageScope (WPILib) {frcYear}", ""));
shortcutData.StartMenuShortcuts.Add(new ShortcutInfo(Path.Join(frcHomePath, "elastic", "elastic_dashboard.exe"), $"Programs/{frcYear} WPILib Tools/Elastic (WPILib) {frcYear}", $"Elastic (WPILib) {frcYear}", ""));
shortcutData.StartMenuShortcuts.Add(new ShortcutInfo(Path.Join(frcHomePath, "qdash", "QDash (WPILib).exe"), $"Programs/{frcYear} WPILib Tools/QDash (WPILib) {frcYear}", $"QDash (WPILib) {frcYear}", ""));

if (toInstallProvider.Model.InstallEverything)
{
Expand Down Expand Up @@ -1095,6 +1098,7 @@ await Task.Run(() =>

CreateLinuxShortcut("AdvantageScope (WPILib)", "AdvantageScope", frcYear, "AdvantageScope (WPILib)", "advantagescope.png", token);
CreateLinuxShortcut("Elastic (WPILib)", "Elastic", frcYear, "elastic_dashboard", "elastic.png", token);
CreateLinuxShortcut("QDash (WPILib)", "QDash", frcYear, "QDash", "qdash.png", token);
CreateLinuxShortcut("Glass", "glass", frcYear, "Glass - DISCONNECTED", "glass.png", token);
CreateLinuxShortcut("OutlineViewer", "outlineviewer", frcYear, "OutlineViewer - DISCONNECTED", "outlineviewer.png", token);
CreateLinuxShortcut("DataLogTool", "datalogtool", frcYear, "Datalog Tool", "datalogtool.png", token);
Expand Down
13 changes: 13 additions & 0 deletions WPILibInstaller-Avalonia/ViewModels/StartPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,17 @@ private async Task<bool> SelectResourceFilesWithFile(string file)
}) ?? throw new InvalidOperationException("Not Valid");
}

entry = zipArchive.GetEntry("qdashConfig.json");

using (StreamReader reader = new StreamReader(entry!.Open()))
{
var configStr = await reader.ReadToEndAsync();
QDashConfig = JsonConvert.DeserializeObject<QDashConfig>(configStr, new JsonSerializerSettings
{
MissingMemberHandling = MissingMemberHandling.Error
}) ?? throw new InvalidOperationException("Not Valid");
}

entry = zipArchive.GetEntry("fullConfig.json");

using (StreamReader reader = new StreamReader(entry!.Open()))
Expand Down Expand Up @@ -439,6 +450,8 @@ public override PageViewModelBase MoveNext()

public ElasticConfig ElasticConfig { get; private set; } = null!;

public QDashConfig QDashConfig { get; private set; } = null!;

public VsCodeConfig VsCodeConfig { get; private set; } = null!;

}
Expand Down
32 changes: 32 additions & 0 deletions apps/ToolsUpdater/src/main/java/Program.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,36 @@ private static void installElastic(String toolsPath) {
}
}

private static void installQDash(String toolsPath) {
// TODO: QDash uses a versioned file for macOS...
if (SystemUtils.IS_OS_MAC) {
String archiveFileName = "QDash-macOS-2026.1.0.tar.gz";
String qdashFolder = Paths.get(new File(toolsPath).getParent(), "qdash").toString();
Path archivePath = Paths.get(qdashFolder, archiveFileName);

try {
Runtime.getRuntime().exec(new String[] {
"tar", "-xzf", archivePath.toString(), "-C", qdashFolder
}).waitFor();

} catch (IOException | InterruptedException e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
try {
if (SystemUtils.IS_OS_WINDOWS) {
Files.copy(Paths.get(toolsPath, "processstarter.exe"), Paths.get(toolsPath, "QDash.exe"), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
// TODO: AppImage?
} else {
Files.copy(Paths.get(toolsPath, "processstarter"), Paths.get(toolsPath, "QDash"), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
}
} catch (IOException e) {
System.out.println(e.toString());
e.printStackTrace();
}
}

private static void installUtility(String toolsPath) {
if (SystemUtils.IS_OS_MAC) {
String archiveFileName = "wpilibutility-mac.tar.gz";
Expand Down Expand Up @@ -184,6 +214,8 @@ public static void main(String[] args) throws URISyntaxException, IOException {
installAdvantageScope(toolsPath);
} else if (tool.name.equals("Elastic")) {
installElastic(toolsPath);
} else if (tool.name.equals("QDash")) {
installQDash(toolsPath);
} else if (tool.name.equals("Utility")) {
installUtility(toolsPath);
} else if (tool.artifact != null) {
Expand Down
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ apply from: 'scripts/maven.gradle'

apply from: 'scripts/advantagescope.gradle'
apply from: 'scripts/elastic.gradle'
apply from: 'scripts/qdash.gradle'

// Tools must happen after maven
apply from: 'scripts/tools.gradle'
Expand Down Expand Up @@ -229,6 +230,7 @@ def generateFullResourcesTask = tasks.register('generateFullResources', project.

advantageScopeZipSetup(it)
elasticZipSetup(it)
qdashZipSetup(it)

if (OperatingSystem.current().isWindows()) {
def task = it
Expand Down Expand Up @@ -334,6 +336,7 @@ def generateConfigFiles = tasks.register('generateCommonResources', Zip) {

advantageScopeConfigFileSetup(zip)
elasticConfigFileSetup(zip)
qdashConfigFileSetup(zip)

vscodeConfigZipSetup(zip)
}
Expand Down
Binary file added icons/qdash.ico
Binary file not shown.
Binary file added icons/qdash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
134 changes: 134 additions & 0 deletions scripts/qdash.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
apply from: 'scripts/versions.gradle'

def baseUrl = "https://git.crueter.xyz/QFRC/QDash/releases/download/$qdashGitTag/"

def fileNameWindows = "QDash-Windows-$qdashGitTag-amd64-msvc-standard.zip"
def downloadUrlWindows = baseUrl + fileNameWindows

def fileNameWindowsArm = "QDash-Windows-$qdashGitTag-arm64-msvc-standard.zip"
def downloadUrlWindowsArm = baseUrl + fileNameWindows

def fileNameMacArm = "QDash-macOS-${qdashGitTag}.tar.gz"
def downloadUrlMacArm = baseUrl + fileNameMacArm

def fileNameLinux = "QDash-Linux-$qdashGitTag-amd64-gcc-standard.AppImage"
def downloadUrlLinux = baseUrl + fileNameLinux

def fileNameLinuxArm = "QDash-Linux-$qdashGitTag-aarch64-gcc-standard.AppImage"
def downloadUrlLinuxArm = baseUrl + fileNameLinux

apply plugin: 'de.undercouch.download'

def downloadTaskWindows = tasks.register('downloadQDashWindows', Download) {
src downloadUrlWindows
def fileName = file(src.file).name
dest "$buildDir/downloads/$fileName"
overwrite true
}

def downloadTaskWindowsArm = tasks.register('downloadQDashWindowsArm', Download) {
src downloadUrlWindowsArm
def fileName = file(src.file).name
dest "$buildDir/downloads/$fileName"
overwrite true
}

def downloadTaskMacArm = tasks.register('downloadQDashMacArm', Download) {
src downloadUrlMacArm
def fileName = file(src.file).name
dest "$buildDir/downloads/$fileName"
overwrite true
}

def downloadTaskLinux = tasks.register('downloadQDashLinux', Download) {
src downloadUrlLinux
def fileName = file(src.file).name
dest "$buildDir/downloads/$fileName"
overwrite true
}

def downloadTaskLinuxArm = tasks.register('downloadQDashLinuxArm', Download) {
src downloadUrlLinuxArm
def fileName = file(src.file).name
dest "$buildDir/downloads/$fileName"
overwrite true
}

def qdashConfigFile = file("$buildDir/qdashConfig.json")

def qdashConfigFileTask = tasks.register('qdashConfigFile') {
it.outputs.file qdashConfigFile

doLast {
def config = [:]
config['folder'] = 'qdash'
config['zipFile'] = 'qdash.zip'

def gbuilder = getGsonBuilder()

gbuilder.setPrettyPrinting()
def json = gbuilder.create().toJson(config)

qdashConfigFile.parentFile.mkdirs()

qdashConfigFile.text = json
}
}

ext.qdashConfigFileSetup = { AbstractArchiveTask zip->
zip.dependsOn qdashConfigFileTask
zip.inputs.file qdashConfigFile

zip.from(qdashConfigFile) {
rename { 'qdashConfig.json' }
}
}

ext.qdashZipSetup = { AbstractArchiveTask zip->
if (project.hasProperty('linuxBuild')) {
zip.dependsOn downloadTaskLinux

zip.inputs.files downloadTaskLinux.get().outputFiles

zip.from(downloadTaskLinux.get().outputFiles.first()) {
into '/qdash'
}
} else if (project.hasProperty('linuxBuildArm64')) {
zip.dependsOn downloadTaskLinuxArm

zip.inputs.files downloadTaskLinuxArm.get().outputFiles

zip.from(downloadTaskLinuxArm.get().outputFiles.first()) {
into '/qdash'
}
} else if (project.hasProperty('macBuildArm')) {
zip.dependsOn downloadTaskMacArm

zip.inputs.files downloadTaskMacArm.get().outputFiles

// Cannot extract, otherwise breaks mac
zip.from(downloadTaskMacArm.get().outputFiles.first()) {
into '/qdash'
}
// TODO: Windows/ARM builds aren't supported yet...
} else if (project.hasProperty('windowsBuildArm')) {
zip.dependsOn downloadTaskWindowsArm

zip.inputs.files downloadTaskWindowsArm.get().outputFiles

zip.from(project.zipTree(downloadTaskWindowsArm.get().outputFiles.first())) {
into '/qdash'
includeEmptyDirs = false
}
} else {
zip.dependsOn downloadTaskWindows

zip.inputs.files downloadTaskWindows.get().outputFiles

zip.from(project.zipTree(downloadTaskWindows.get().outputFiles.first())) {
into '/qdash'
includeEmptyDirs = false
}
}
}

5 changes: 5 additions & 0 deletions scripts/tools.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ def toolsJsonTask = tasks.register('toolsJson', Task) {
elasticItem['version'] = elasticGitTag
config << elasticItem

def qdashItem = [:]
qdashItem['name'] = "QDash"
qdashItem['version'] = qdashGitTag
config << qdashItem

def utilityItem = [:]
utilityItem['name'] = "Utility"
utilityItem['version'] = wpilibVersion
Expand Down
2 changes: 2 additions & 0 deletions scripts/versions.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ ext.advantagescopeGitTag = 'v26.0.0'

ext.elasticGitTag = 'v2026.1.1'

ext.qdashGitTag = '2026.1.0'

ext.frcYear = '2026'

ext.gradleWrapperVersion = '8.11'