diff options
author | Norbert Preining <preining@logic.at> | 2017-09-27 01:23:23 +0000 |
---|---|---|
committer | Norbert Preining <preining@logic.at> | 2017-09-27 01:23:23 +0000 |
commit | 7b0ea79a18ffb1145ef32bc978d45d41cbd4f6e0 (patch) | |
tree | ef36c3c7022994739d9c3c3cf2b088b60cf53a1d /Master/texmf-dist/source/support | |
parent | d0f69395b9ee2350e2263c8c6d249d58bf96dc89 (diff) |
update tlcockpit
git-svn-id: svn://tug.org/texlive/trunk@45409 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/support')
-rw-r--r-- | Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala | 485 | ||||
-rw-r--r-- | Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLPackage.scala | 6 |
2 files changed, 284 insertions, 207 deletions
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala index 938a91bc5ef..f76a34d2f75 100644 --- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala +++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala @@ -11,7 +11,7 @@ import TeXLive.{TLPackage, TlmgrProcess} import scala.concurrent.{Future, SyncVar} import scala.concurrent.ExecutionContext.Implicits.global import scala.util.{Failure, Success} -import scalafx.geometry.HPos +import scalafx.geometry.{HPos, Pos, VPos} import scalafx.scene.control.Alert.AlertType // needed see https://github.com/scalafx/scalafx/issues/137 @@ -28,6 +28,7 @@ import scalafx.event.ActionEvent import scalafx.collections.ObservableBuffer import scala.sys.process._ import scala.collection.mutable.ArrayBuffer +import scalafx.scene.text._ object ApplicationMain extends JFXApp { @@ -36,10 +37,11 @@ object ApplicationMain extends JFXApp { override def stopApp(): Unit = { tlmgr.cleanup() } - + val pkgs = ArrayBuffer[TLPackage]() val viewpkgs = ObservableBuffer[TLPackage]() + val updpkgs = ObservableBuffer[TLPackage]() val errorText = ObservableBuffer[String]() val outputText = ObservableBuffer[String]() @@ -99,11 +101,11 @@ object ApplicationMain extends JFXApp { val cmdline = new TextField() val tlmgr = new TlmgrProcess( // (s:String) => outputfield.text = s, - (s:Array[String]) => { + (s: Array[String]) => { outputText.clear() outputText.appendAll(s) }, - (s:String) => { + (s: String) => { errorText.clear() errorText.append(s) if (s != "") { @@ -116,7 +118,9 @@ object ApplicationMain extends JFXApp { errorText.clear() outputText.clear() outerrpane.expanded = false - val foo = Future { tlmgr.send_command(s) } + val foo = Future { + tlmgr.send_command(s) + } foo onComplete { case Success(ret) => f(ret) case Failure(t) => @@ -127,13 +131,13 @@ object ApplicationMain extends JFXApp { } def update_update_button_state(): Unit = { - update_all_button.disable = ! pkgs.foldLeft(false)( - (a,b) => a || (if (b.name.value == "texlive.infra") false else b.lrev.value.toInt > 0 && b.lrev.value.toInt < b.rrev.value.toInt) + update_all_button.disable = !pkgs.foldLeft(false)( + (a, b) => a || (if (b.name.value == "texlive.infra") false else b.lrev.value.toInt > 0 && b.lrev.value.toInt < b.rrev.value.toInt) ) // TODO we should change pkgs to a Map with keys are the names + repository (for multi repo support) // and the values are llrev/rrev or some combination - update_self_button.disable = ! pkgs.foldLeft(false)( - (a,b) => a || (if (b.name.value == "texlive.infra") b.lrev.value.toInt < b.rrev.value.toInt else false) + update_self_button.disable = !pkgs.foldLeft(false)( + (a, b) => a || (if (b.name.value == "texlive.infra") b.lrev.value.toInt < b.rrev.value.toInt else false) ) } @@ -143,32 +147,10 @@ object ApplicationMain extends JFXApp { sys.exit(0) } - def callback_load_update_info(s:String, strs: Array[String]): Unit = { - if (s == "remote") { - tlmgr_async_command("info --data name,localrev,remoterev,shortdesc", (s: Array[String]) => { - val newpkgs = ArrayBuffer[TLPackage]() - s.map((line:String) => { - val fields: Array[String] = line.split(",", -1) - val sd = fields(3) - val shortdesc = if (sd.isEmpty) "" else sd.substring(1).dropRight(1).replace("""\"""",""""""") - newpkgs += new TLPackage(fields(0), fields(1), fields(2), shortdesc) - }) - pkgs.clear() - newpkgs.map(pkgs += _) - viewpkgs.clear() - pkgs.map(viewpkgs += _) - // check for updates available - update_update_button_state() - }) - } - } - - def callback_load(s: String): Unit = { - tlmgr_async_command("load " + s, callback_load_update_info(s, _) ) - } def callback_run_text(s: String): Unit = { tlmgr_async_command(s, (s: Array[String]) => {}) } + def callback_run_cmdline(): Unit = { callback_run_text(cmdline.text.value) outerrpane.expanded = true @@ -216,14 +198,17 @@ object ApplicationMain extends JFXApp { contentText = "Brought to you by Norbert\nSources: https://github.com/TeX-Live/tlcockpit" }.showAndWait() } - def callback_show_all() : Unit = { + + /* def callback_show_all(): Unit = { viewpkgs.clear() pkgs.map(viewpkgs += _) } - def callback_show_installed() : Unit = { + + def callback_show_installed(): Unit = { viewpkgs.clear() pkgs.map(p => if (p.lrev.value.toInt > 0) viewpkgs += p) } + def callback_show_updates(): Unit = { val newpkgs = ArrayBuffer[TLPackage]() pkgs.map(p => @@ -235,18 +220,21 @@ object ApplicationMain extends JFXApp { viewpkgs.clear() newpkgs.map(viewpkgs += _) } - def callback_update_all() : Unit = { + */ + + def callback_update_all(): Unit = { tlmgr_async_command("update --all", s => { update_update_button_state() - callback_show_all() + // callback_show_all() }) } - def callback_update_self() : Unit = { + + def callback_update_self(): Unit = { // TODO // should we restart tlmgr here - it might be necessary!!! tlmgr_async_command("update --self", s => { update_update_button_state() - callback_show_all() + // callback_show_all() }) } @@ -288,176 +276,255 @@ object ApplicationMain extends JFXApp { }) } + val mainMenu = new Menu("TLCockpit") { + items = List( + new MenuItem("Update filename database ...") { + onAction = (ae) => callback_run_external("mktexlsr") + }, + // calling fmtutil kills JavaFX when the first sub-process (format) is called + // I get loads of Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException + // new MenuItem("Rebuild all formats ...") { onAction = (ae) => callback_run_external("fmtutil --sys --all") }, + new MenuItem("Update font map database ...") { + onAction = (ae) => callback_run_external("updmap --sys") + }, + /* + new MenuItem("Restore packages from backup ...") { + disable = true; onAction = (ae) => not_implemented_info() + }, + new MenuItem("Handle symlinks in system dirs ...") { + disable = true; onAction = (ae) => not_implemented_info() + }, + new SeparatorMenuItem, + new MenuItem("Remove TeX Live ...") { + disable = true; onAction = (ae) => not_implemented_info() + }, + */ + new SeparatorMenuItem, + // temporarily move here as we disable the Help menu + new MenuItem("About") { + onAction = (ae) => callback_about() + }, + new MenuItem("Exit") { + onAction = (ae: ActionEvent) => callback_quit() + }) + } + val optionsMenu = new Menu("Options") { + items = List( + new MenuItem("General ...") { + disable = true; onAction = (ae) => not_implemented_info() + }, + new MenuItem("Paper ...") { + disable = true; onAction = (ae) => not_implemented_info() + }, + new MenuItem("Platforms ...") { + disable = true; onAction = (ae) => not_implemented_info() + }, + new SeparatorMenuItem, + new CheckMenuItem("Expert options") { + disable = true + }, + new CheckMenuItem("Enable debugging options") { + disable = true + }, + new CheckMenuItem("Disable auto-install of new packages") { + disable = true + }, + new CheckMenuItem("Disable auto-removal of server-deleted packages") { + disable = true + } + ) + } + val helpMenu = new Menu("Help") { + items = List( + /* + new MenuItem("Manual") { + disable = true; onAction = (ae) => not_implemented_info() + }, + */ + new MenuItem("About") { + onAction = (ae) => callback_about() + }, + ) + } + val expertPane = new TitledPane { + text = "Experts only" + collapsible = true + expanded = false + content = new VBox { + spacing = 10 + children = List( + new HBox { + spacing = 10 + children = List( + new Label("tlmgr shell command:") { + // TODO vertical text alignment does not work + textAlignment = TextAlignment.Center + }, + cmdline, + new Button { + text = "Go" + onAction = (event: ActionEvent) => callback_run_cmdline() + } + ) + }, + /* new HBox { + spacing = 10 + children = List( + new Button { + text = "Show updates" + onAction = (e: ActionEvent) => callback_show_updates() + }, + new Button { + text = "Show installed" + onAction = (e: ActionEvent) => callback_show_installed() + }, + new Button { + text = "Show all" + onAction = (e: ActionEvent) => callback_show_all() + }, + update_self_button, + update_all_button + ) + } + */ + ) + } + } + val updateTable = { + val colName = new TableColumn[TLPackage, String] { + text = "Package" + cellValueFactory = { _.value.name } + prefWidth = 150 + } + val colDesc = new TableColumn[TLPackage, String] { + text = "Description" + cellValueFactory = { _.value.shortdesc } + prefWidth = 300 + } + val colLRev = new TableColumn[TLPackage, String] { + text = "Local rev" + cellValueFactory = { _.value.lrev } + prefWidth = 100 + } + val colRRev = new TableColumn[TLPackage, String] { + text = "Remote rev" + cellValueFactory = { _.value.rrev } + prefWidth = 100 + } + val colSize = new TableColumn[TLPackage, String] { + text = "Size" + cellValueFactory = { _.value.size } + prefWidth = 100 + } + val table = new TableView[TLPackage](updpkgs) { + columns ++= List(colName, colDesc, colLRev, colRRev, colSize) + } + colDesc.prefWidth.bind(table.width - colName.width - colLRev.width - colRRev.width - colSize.width) + table.prefHeight = 300 + table.vgrow = Priority.Always + table.rowFactory = { _ => + val row = new TableRow[TLPackage] {} + val ctm = new ContextMenu( + new MenuItem("Info") { + onAction = (ae) => callback_show_pkg_info(row.item.value.name.value) + }, + new MenuItem("Install") { + onAction = (ae) => callback_run_text("install " + row.item.value.name.value) + }, + new MenuItem("Remove") { + onAction = (ae) => callback_run_text("remove " + row.item.value.name.value) + }, + new MenuItem("Update") { + onAction = (ae) => callback_run_text("update " + row.item.value.name.value) + } + ) + row.contextMenu = ctm + row + } + table + } + val packageTable = { + val colName = new TableColumn[TLPackage, String] { + text = "Package" + cellValueFactory = { _.value.name } + prefWidth = 150 + } + val colLRev = new TableColumn[TLPackage, String] { + text = "Local rev" + cellValueFactory = { _.value.lrev } + prefWidth = 100 + } + val colRRev = new TableColumn[TLPackage, String] { + text = "Remote rev" + cellValueFactory = { _.value.rrev } + prefWidth = 100 + } + val colDesc = new TableColumn[TLPackage, String] { + text = "Description" + cellValueFactory = { _.value.shortdesc } + prefWidth = 300 + } + val colInst = new TableColumn[TLPackage, String] { + text = "Installed" + cellValueFactory = { _.value.installed } + prefWidth = 30 + } + val table = new TableView[TLPackage](viewpkgs) { + columns ++= List(colName, colDesc, colInst, colLRev, colRRev) + } + colDesc.prefWidth.bind(table.width - colLRev.width - colRRev.width - colInst.width - colName.width) + table.prefHeight = 300 + table.vgrow = Priority.Always + table.rowFactory = { _ => + val row = new TableRow[TLPackage] {} + val ctm = new ContextMenu( + new MenuItem("Info") { + onAction = (ae) => callback_show_pkg_info(row.item.value.name.value) + }, + new MenuItem("Install") { + onAction = (ae) => callback_run_text("install " + row.item.value.name.value) + }, + new MenuItem("Remove") { + onAction = (ae) => callback_run_text("remove " + row.item.value.name.value) + }, + new MenuItem("Update") { + onAction = (ae) => callback_run_text("update " + row.item.value.name.value) + } + ) + row.contextMenu = ctm + row + } + table + } + val pkgstabs = new TabPane { + minWidth = 400 + vgrow = Priority.Always + tabs = Seq( + new Tab { + text = "Updates" + closable = false + content = updateTable + }, + new Tab { + text = "Packages" + closable = false + content = packageTable + } + ) + } stage = new PrimaryStage { title = "TLCockpit" scene = new Scene { root = { val topBox = new MenuBar { useSystemMenuBar = true - menus.add(new Menu("TLCockpit") { - items = List( - new MenuItem("Load default (from tlpdb) repository") { - onAction = (ae: ActionEvent) => callback_load("remote") - }, - new MenuItem("Load standard net repository") { - onAction = (ae: ActionEvent) => not_implemented_info() - disable = true - }, - new MenuItem("Load other repository ...") { - onAction = (ae: ActionEvent) => not_implemented_info() - disable = true - }, - new SeparatorMenuItem, - new MenuItem("Exit") { - onAction = (ae: ActionEvent) => callback_quit() - } - ) - }) - menus.add(new Menu("Options") { - items = List( - new MenuItem("General ...") { disable = true; onAction = (ae) => not_implemented_info() }, - new MenuItem("Paper ...") { disable = true; onAction = (ae) => not_implemented_info() }, - new MenuItem("Platforms ...") { disable = true; onAction = (ae) => not_implemented_info() }, - new SeparatorMenuItem, - new CheckMenuItem("Expert options") { disable = true }, - new CheckMenuItem("Enable debugging options") { disable = true }, - new CheckMenuItem("Disable auto-install of new packages") { disable = true }, - new CheckMenuItem("Disable auto-removal of server-deleted packages") { disable = true } - ) - }) - menus.add(new Menu("Actions") { - items = List( - new MenuItem("Update filename database ...") { onAction = (ae) => callback_run_external("mktexlsr") }, - // calling fmtutil kills JavaFX when the first sub-process (format) is called - // I get loads of Exception in thread "JavaFX Application Thread" java.lang.ArrayIndexOutOfBoundsException - // new MenuItem("Rebuild all formats ...") { onAction = (ae) => callback_run_external("fmtutil --sys --all") }, - new MenuItem("Update font map database ...") { onAction = (ae) => callback_run_external("updmap --sys") }, - new MenuItem("Restore packages from backup ...") { disable = true; onAction = (ae) => not_implemented_info() }, - new MenuItem("Handle symlinks in system dirs ...") { disable = true; onAction = (ae) => not_implemented_info() }, - new SeparatorMenuItem, - new MenuItem("Remove TeX Live ...") { disable = true; onAction = (ae) => not_implemented_info() } - ) - }) - menus.add(new Menu("Help") { - items = List( - new MenuItem("Manual") { disable = true; onAction = (ae) => not_implemented_info() }, - new MenuItem("About") { onAction = (ae) => callback_about() }, - ) - }) + // menus.addAll(mainMenu, optionsMenu, helpMenu) + menus.addAll(mainMenu) } val centerBox = new VBox { padding = Insets(10) - children = List( - new TitledPane { - text = "Actions" - collapsible = false - content = new VBox { - spacing = 10 - children = List( - new HBox { - spacing = 10 - children = List( - cmdline, - new Button { - text = "Go" - onAction = (event: ActionEvent) => callback_run_cmdline() - }, - new Button { - text = "Load repository"; - onAction = (event: ActionEvent) => callback_load("remote") - } - ) - }, - new HBox { - spacing = 10 - children = List( - new Button { - text = "Show updates" - onAction = (e: ActionEvent) => callback_show_updates() - }, - new Button { - text = "Show installed" - onAction = (e: ActionEvent) => callback_show_installed() - }, - new Button { - text = "Show all" - onAction = (e: ActionEvent) => callback_show_all() - }, - update_self_button, - update_all_button - ) - } - ) - } - }, - outerrpane, - { - val col1 = new TableColumn[TLPackage, String] { - text = "Package" - cellValueFactory = { - _.value.name - } - prefWidth = 150 - } - val col2 = new TableColumn[TLPackage, String] { - text = "Local rev" - cellValueFactory = { - _.value.lrev - } - prefWidth = 100 - } - val col3 = new TableColumn[TLPackage, String] { - text = "Remote rev" - cellValueFactory = { - _.value.rrev - } - prefWidth = 100 - } - val col4 = new TableColumn[TLPackage, String] { - text = "Description" - cellValueFactory = { - _.value.shortdesc - } - prefWidth = 300 - } - val table = new TableView[TLPackage](viewpkgs) { - columns ++= List(col1,col2,col3,col4) - } - col4.prefWidth.bind(table.width - col1.width - col2.width - col3.width) - table.prefHeight = 300 - table.vgrow = Priority.Always - table.rowFactory = { _ => - val row = new TableRow[TLPackage] {} - val ctm = new ContextMenu( - new MenuItem("Info") { onAction = (ae) => callback_show_pkg_info(row.item.value.name.value) }, - new MenuItem("Install") { - onAction = (ae) => callback_run_text("install " + row.item.value.name.value) - }, - new MenuItem("Remove") { - onAction = (ae) => callback_run_text("remove " + row.item.value.name.value) - }, - new MenuItem("Update") { - onAction = (ae) => callback_run_text("update " + row.item.value.name.value) - } - ) - row.contextMenu = ctm - row - } - table - }, - ) + children = List(pkgstabs, expertPane, outerrpane) } - /* val bottomBox = new HBox { - padding = Insets(10) - spacing = 10 - children = List( - new Button { - text = "Quit" - onAction = (event: ActionEvent) => callback_quit() - } - ) - } - */ new BorderPane { // padding = Insets(20) top = topBox @@ -498,18 +565,24 @@ object ApplicationMain extends JFXApp { // load the initial set of packages var pkglines: Array[String] = Array() - tlmgr_async_command("info --only-installed --data name,localrev,shortdesc", (s: Array[String]) => { - s.map(line => { - val fields: Array[String] = line.split(",", -1) - val sd = if (fields(2).isEmpty) "" else fields(2).substring(1).dropRight(1).replace("""\"""",""""""") - pkgs += new TLPackage(fields(0), fields(1), "0", sd) + // tlmgr loads local and remote if we request localrev and remoterev! + tlmgr_async_command("info --data name,localrev,remoterev,shortdesc,size,installed", (s: Array[String]) => { + val newpkgs = ArrayBuffer[TLPackage]() + s.map((line: String) => { + val fields: Array[String] = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1) + val sd = fields(3) + val shortdesc = if (sd.isEmpty) "" else sd.substring(1).dropRight(1).replace("""\"""",""""""") + pkgs += new TLPackage(fields(0), fields(1), fields(2), shortdesc, fields(4), fields(5)) }) - viewpkgs.clear() - pkgs.map(viewpkgs += _) + pkgs.map(pkg => { + viewpkgs += pkg + if (pkg.installed.value == "1" && pkg.lrev.value.toInt < pkg.rrev.value.toInt) updpkgs += pkg + }) + // check for updates available + update_update_button_state() // Platform.runLater { startalert.close() } }) - } // object ApplicationMain // vim:set tabstop=2 expandtab : // diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLPackage.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLPackage.scala index 1f79744fc7f..cb9d8c7e88e 100644 --- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLPackage.scala +++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLPackage.scala @@ -1,10 +1,14 @@ package TeXLive import scalafx.beans.property.StringProperty +import scalafx.beans.property.IntegerProperty +import scalafx.beans.property.BooleanProperty -class TLPackage(name_ : String, lrev_ : String, rrev_ : String, shortdesc_ : String) { +class TLPackage(name_ : String, lrev_ : String, rrev_ : String, shortdesc_ : String, size_ : String, installed_ : String) { val name = new StringProperty(this, "name", name_) val shortdesc = new StringProperty(this, "shortdesc", shortdesc_) val lrev = new StringProperty(this, "revision", lrev_) val rrev = new StringProperty(this, "revision", rrev_) + val size = new StringProperty(this, "size", size_) + val installed = new StringProperty(this, "installed", installed_) } |