summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
authorNorbert Preining <preining@logic.at>2017-10-12 05:19:26 +0000
committerNorbert Preining <preining@logic.at>2017-10-12 05:19:26 +0000
commitfa79130908eed3e87903a6b9ecc2f2c7dd014c83 (patch)
tree2cdc93ed4c6419fe3b1c3cf4e56a793d0f851376 /Master
parent8fa36ac3a44c9645b949dabd122622dc121b1359 (diff)
tlcockpit v0.6
git-svn-id: svn://tug.org/texlive/trunk@45526 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r--Master/texmf-dist/doc/support/tlcockpit/NEWS5
-rw-r--r--Master/texmf-dist/scripts/tlcockpit/tlcockpit.jarbin11688515 -> 11704983 bytes
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/build.sbt2
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala225
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala13
5 files changed, 171 insertions, 74 deletions
diff --git a/Master/texmf-dist/doc/support/tlcockpit/NEWS b/Master/texmf-dist/doc/support/tlcockpit/NEWS
index c1dca4d41ad..d8c84e675e8 100644
--- a/Master/texmf-dist/doc/support/tlcockpit/NEWS
+++ b/Master/texmf-dist/doc/support/tlcockpit/NEWS
@@ -1,5 +1,10 @@
NEWS for tlcockpit
+version 0.6
+-----------
+- texlive infra updates handled properly (restarting tlmgr)
+- scrollable list of files in pkg info window
+
version 0.5
-----------
- better pkg info display
diff --git a/Master/texmf-dist/scripts/tlcockpit/tlcockpit.jar b/Master/texmf-dist/scripts/tlcockpit/tlcockpit.jar
index ac6b87c2777..0a57df3631f 100644
--- a/Master/texmf-dist/scripts/tlcockpit/tlcockpit.jar
+++ b/Master/texmf-dist/scripts/tlcockpit/tlcockpit.jar
Binary files differ
diff --git a/Master/texmf-dist/source/support/tlcockpit/build.sbt b/Master/texmf-dist/source/support/tlcockpit/build.sbt
index a054c933ca8..fb5cf2f98d3 100644
--- a/Master/texmf-dist/source/support/tlcockpit/build.sbt
+++ b/Master/texmf-dist/source/support/tlcockpit/build.sbt
@@ -1,6 +1,6 @@
name := "tlcockpit"
-version := "0.5"
+version := "0.6"
scalaVersion := "2.12.3"
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 d7b7162107e..696744bbeb1 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
@@ -21,7 +21,7 @@ import scala.concurrent.ExecutionContext.Implicits.global
// import scala.reflect.io.File
import scala.util.{Failure, Success}
import scalafx.beans.property.ObjectProperty
-import scalafx.geometry.{HPos, Pos, VPos}
+import scalafx.geometry.{HPos, Pos, VPos, Orientation}
import scalafx.scene.Cursor
import scalafx.scene.control.Alert.AlertType
import scalafx.scene.image.{Image, ImageView}
@@ -32,6 +32,7 @@ import scalafx.scene.control.TableColumn._
import scalafx.scene.control.TreeTableColumn._
import scalafx.scene.control.TreeItem
import scalafx.scene.control.Menu._
+import scalafx.scene.control.ListCell
import scalafx.scene.control.cell._
import scalafx.scene.text.Text
import scalafx.Includes._
@@ -48,11 +49,10 @@ import scalafx.collections.ObservableMap
// import java.awt.Desktop
+// TODO when installing a collection list the additionally installed packages, too
+// TODO idea pkg tree with collection -> packages
+// TODO pkg info listview adjust height according to font size and # of items
// TODO TreeTableView indentation is lazy
-// TODO pkg info - allow opening (maybe preview) of doc files
-// use WebView and pdf.js: https://stackoverflow.com/questions/18207116/displaying-pdf-in-javafx
-// see https://github.com/scalafx/scalafx-ensemble/blob/master/src/main/scala/scalafx/ensemble/example/web/EnsembleWebView.scala
-// TODO better layout of pkg info
object ApplicationMain extends JFXApp {
@@ -128,24 +128,6 @@ object ApplicationMain extends JFXApp {
(ae: KeyEvent) => if (ae.code == KeyCode.Enter) callback_run_cmdline()
}
val outputLine = new SyncVar[String]
- val tlmgr = new TlmgrProcess(
- // (s:String) => outputfield.text = s,
- (s: Array[String]) => {
- // we don't wont normal output to be displayed
- // as it is anyway returned
- // outputText.clear()
- // outputText.appendAll(s)
- },
- (s: String) => {
- // errorText.clear()
- errorText.append(s)
- if (s.trim != "") {
- outerrpane.expanded = true
- outerrtabs.selectionModel().select(1)
- }
- },
- (s: String) => outputLine.put(s)
- )
def tlmgr_async_command(s: String, f: Array[String] => Unit): Unit = {
errorText.clear()
@@ -307,11 +289,22 @@ object ApplicationMain extends JFXApp {
}
}
}
- tlmgr_async_command(s"update $s", _ => {
- Platform.runLater { lineUpdateFunc = { (s: String) => } }
+ // val cmd = if (s == "--self") "update --self --no-restart" else s"update $s"
+ val cmd = if (s == "--self") "update --self" else s"update $s"
+ tlmgr_async_command(cmd, _ => {
+ Platform.runLater {
+ lineUpdateFunc = { (s: String) => }
+ if (s == "--self") {
+ reinitialize_tlmgr()
+ // this doesn't work seemingly
+ // update_upds_list()
+ }
+ }
})
}
+
+
def do_one_pkg(what: String, pkg: String): Unit = {
tlmgr_async_command(s"$what $pkg", _ => { Platform.runLater { update_pkgs_lists() } })
}
@@ -388,7 +381,9 @@ object ApplicationMain extends JFXApp {
}
// for ismixed we && all the installed status. If all are installed, we get true
val allinstalled = (kids :+ p).foldRight[Boolean](true)((k, b) => k.installed.value == "Installed" && b)
- if (!allinstalled) {
+ val someinstalled = (kids :+ p).exists(_.installed.value == "Installed")
+ val mixedinstalled = !allinstalled && someinstalled
+ if (mixedinstalled) {
// replace installed status with "Mixed"
new TreeItem[TLPackage](new TreeItem[TLPackage](
new TLPackage(p.name.value, p.lrev.value.toString, p.rrev.value.toString, p.shortdesc.value, p.size.value.toString, "Mixed")
@@ -418,7 +413,8 @@ object ApplicationMain extends JFXApp {
}
if (doit) {
val infraAvailable = upds.keys.exists(_.startsWith("texlive.infra"))
- val updatesAvailable = upds.keys.exists(p => !p.startsWith("texlive.infra"))
+ // only allow for updates of other packages when no infra update available
+ val updatesAvailable = !infraAvailable && upds.keys.exists(p => !p.startsWith("texlive.infra") && !(p == "root"))
val newroot = new TreeItem[TLUpdate](new TLUpdate("root", "", "", "", "", "")) {
children = upds
.filter(_._1 != "root")
@@ -430,10 +426,22 @@ object ApplicationMain extends JFXApp {
update_self_menu.disable = !infraAvailable
update_all_menu.disable = !updatesAvailable
updateTable.root = newroot
+ if (infraAvailable) {
+ texlive_infra_update_warning()
+ }
}
}
})
+ def texlive_infra_update_warning(): Unit = {
+ new Alert(AlertType.Warning) {
+ initOwner(stage)
+ title = "TeX Live Infrastructure Update Available"
+ headerText = "Updates to the TeX Live Manager (Infrastructure) available."
+ contentText = "Please use \"Update self\" from the Menu!"
+ }.showAndWait()
+ }
+
def update_bkps_list(): Unit = {
tlmgr_async_command("restore", lines => {
// lines.drop(1).foreach(println(_))
@@ -511,8 +519,13 @@ object ApplicationMain extends JFXApp {
val foo = parse_one_update_line(l)
(foo.name.value, foo)
}.toMap
+ val infraAvailable = newupds.keys.exists(_.startsWith("texlive.infra"))
upds.clear()
- upds ++= newupds
+ if (infraAvailable) {
+ upds ++= Seq( ("texlive.infra", newupds("texlive.infra") ) )
+ } else {
+ upds ++= newupds
+ }
trigger_update("upds")
})
}
@@ -527,6 +540,47 @@ object ApplicationMain extends JFXApp {
bkps("root") = Map[String,TLBackup](("0", new TLBackup("root","0","0")))
}
+ def doListView(files: Seq[String], clickable: Boolean): scalafx.scene.Node = {
+ if (files.length <= 5) {
+ val vb = new VBox()
+ vb.children = files.map { f =>
+ val fields = f.split(" ")
+ new Label(fields(0)) {
+ if (clickable) {
+ textFill = Color.Blue
+ onMouseClicked = { me: MouseEvent => OsTools.openFile(tlmgr.tlroot + "/" + fields(0)) }
+ cursor = Cursor.Hand
+ }
+ }
+ }
+ vb
+ } else {
+ val vb = new ListView[String] {}
+ vb.minHeight = 150
+ vb.prefHeight = 150
+ vb.maxHeight = 200
+ vb.vgrow = Priority.Always
+ // TODO tighter spacing for ListView
+ vb.orientation = Orientation.Vertical
+ vb.cellFactory = { p => {
+ val foo = new ListCell[String]
+ foo.item.onChange { (_, _, str) => foo.text = str }
+ if (clickable) {
+ foo.textFill = Color.Blue
+ foo.onMouseClicked = { me: MouseEvent => OsTools.openFile(tlmgr.tlroot + "/" + foo.text.value) }
+ foo.cursor = Cursor.Hand
+ }
+ foo
+ }
+ }
+ // vb.children = docFiles.map { f =>
+ vb.items = ObservableBuffer(files.map { f =>
+ val fields = f.split(" ")
+ fields(0)
+ })
+ vb
+ }
+ }
def callback_show_pkg_info(pkg: String): Unit = {
tlmgr_async_command(s"info --list $pkg", pkginfo => {
@@ -539,6 +593,7 @@ object ApplicationMain extends JFXApp {
resizable = true
}
dialog.dialogPane().buttonTypes = Seq(ButtonType.OK)
+ val isInstalled = pkgs(pkg).installed.value == "Installed"
val grid = new GridPane() {
hgap = 10
vgap = 10
@@ -569,6 +624,7 @@ object ApplicationMain extends JFXApp {
"unknown"
if (keyval.length == 2) {
if (keyval(0) == "doc files" || keyval(0) == "source files" || keyval(0) == "run files" ||
+ keyval(0).startsWith("depending package ") ||
keyval(0).startsWith("bin files (all platforms)") || keyval(0).startsWith("Included files, by type")) {
// do nothing
} else {
@@ -583,47 +639,34 @@ object ApplicationMain extends JFXApp {
}
})
// add files section
- if (runFiles.nonEmpty) {
- grid.add(new Label("run files"), 0, crow)
- grid.add(new Label(runFiles.mkString("\n")) { wrapText = true },1, crow)
- crow += 1
- }
if (docFiles.nonEmpty) {
grid.add(new Label("doc files"), 0, crow)
- val vb = new VBox()
- vb.children = docFiles.map { f =>
- val fields = f.split(" ")
- new Label(fields(0)) {
- textFill = Color.Blue
- onMouseClicked = { me: MouseEvent =>
- println("Do something with " + fields(0))
- // TODO while does gio return immediately on bash prompt but not here?
- // ("gio open " + tlmgr.tlroot + "/" + fields(0)).!
- //Desktop.getDesktop().open((tlmgr.tlroot + "/" + fields(0)))
- OsTools.openFile(tlmgr.tlroot + "/" + fields(0))
- println("done")
- }
- cursor = Cursor.Hand
- }
- }
//grid.add(new Label(docFiles.mkString("\n")) { wrapText = true },1, crow)
- grid.add(vb,1,crow)
+ grid.add(doListView(docFiles.map(s => s.replaceFirst("RELOC","texmf-dist")),isInstalled),1,crow)
+ crow += 1
+ }
+ if (runFiles.nonEmpty) {
+ grid.add(new Label("run files"), 0, crow)
+ // grid.add(new Label(runFiles.mkString("\n")) { wrapText = true },1, crow)
+ grid.add(doListView(runFiles.map(s => s.replaceFirst("RELOC","texmf-dist")),false),1,crow)
crow += 1
}
if (srcFiles.nonEmpty) {
grid.add(new Label("src files"), 0, crow)
- grid.add(new Label(srcFiles.mkString("\n")) { wrapText = true },1, crow)
+ // grid.add(new Label(srcFiles.mkString("\n")) { wrapText = true },1, crow)
+ grid.add(doListView(srcFiles.map(s => s.replaceFirst("RELOC","texmf-dist")),false),1,crow)
crow += 1
}
if (binFiles.nonEmpty) {
grid.add(new Label("bin files"), 0, crow)
- grid.add(new Label(binFiles.mkString("\n")) { wrapText = true },1, crow)
+ // grid.add(new Label(binFiles.mkString("\n")) { wrapText = true },1, crow)
+ grid.add(doListView(binFiles.map(s => s.replaceFirst("RELOC","texmf-dist")),false),1,crow)
crow += 1
}
- grid.columnConstraints = Seq(new ColumnConstraints(100, 150, 200), new ColumnConstraints(100, 300, 5000, Priority.Always, new HPos(HPos.Left), true))
+ grid.columnConstraints = Seq(new ColumnConstraints(100, 200, 200), new ColumnConstraints(100, 400, 5000, Priority.Always, new HPos(HPos.Left), true))
dialog.dialogPane().content = grid
- // dialog.width = 500
- // dialog.height = 800
+ dialog.width = 600
+ dialog.height = 1500
dialog.showAndWait()
}
})
@@ -1040,6 +1083,61 @@ object ApplicationMain extends JFXApp {
icons.add(iconImage)
}
+
+
+ def initialize_tlmgr(): TlmgrProcess = {
+ val tt = new TlmgrProcess(
+ // (s:String) => outputfield.text = s,
+ (s: Array[String]) => {
+ // we don't wont normal output to be displayed
+ // as it is anyway returned
+ // outputText.clear()
+ // outputText.appendAll(s)
+ },
+ (s: String) => {
+ // errorText.clear()
+ errorText.append(s)
+ if (s.trim != "") {
+ outerrpane.expanded = true
+ outerrtabs.selectionModel().select(1)
+ }
+ },
+ (s: String) => outputLine.put(s)
+ )
+ val bar = Future {
+ while (true) {
+ val s = outputLine.take
+ lineUpdateFunc(s)
+ }
+ }
+ bar.onComplete {
+ case Success(value) => println(s"Got the callback, meaning = $value")
+ case Failure(e) =>
+ println("lineUpdateFunc thread got interrupted -- probably old tlmgr, ignoring it!")
+ //e.printStackTrace
+ }
+ tt
+ }
+
+ def reinitialize_tlmgr(): Unit = {
+ tlmgr.cleanup()
+ // Thread.sleep(1000)
+ tlmgr = initialize_tlmgr()
+ tlmgr_post_init()
+ pkgstabs.getSelectionModel().select(0)
+ }
+
+ def tlmgr_post_init():Unit = {
+ tlmgr.start_process()
+ tlmgr.get_output_till_prompt()
+ // update_pkg_lists_to_be_renamed() // this is async done
+ pkgs.clear()
+ upds.clear()
+ bkps.clear()
+ update_pkgs_lists()
+ }
+
+
/* TODO implement splash screen - see example in ProScalaFX
val startalert = new Alert(AlertType.Information)
startalert.setTitle("Loading package database ...")
@@ -1058,21 +1156,8 @@ object ApplicationMain extends JFXApp {
*/
var lineUpdateFunc: String => Unit = { (l: String) => } // println(s"DEBUG: got ==$l== from tlmgr") }
-
- val bar = Future {
- while (true) {
- val s = outputLine.take
- try {
- lineUpdateFunc(s)
- } catch {
- case e: Exception => println("SOMETHING BAD IN lineUpdateFUnc happened: " + e + "\n")
- }
- }
- }
- tlmgr.start_process()
- tlmgr.get_output_till_prompt()
- // update_pkg_lists_to_be_renamed() // this is async done
- update_pkgs_lists()
+ var tlmgr = initialize_tlmgr()
+ tlmgr_post_init()
} // object ApplicationMain
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala
index 33c76d6708c..169f44154fb 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala
@@ -128,6 +128,7 @@ class TlmgrProcess(updout: Array[String] => Unit, upderr: String => Unit, updlin
} catch {
case exc: Throwable =>
stdin.close()
+ // println("Exception in inputFn thread: " + exc + "\n")
errorBuffer.append(" Input thread: Exception: " + exc + "\n")
}
}
@@ -139,19 +140,24 @@ class TlmgrProcess(updout: Array[String] => Unit, upderr: String => Unit, updlin
while (true) {
line = reader.readLine
if (line == null) {
- // println("DDD: got null line")
// println("Did read NULL from stdin giving up")
// error = true
} else {
- // println("did read " + line + " from process")
+ // println("DDD did read " + line + " from process")
outputString.put(line)
- updline(line)
+ try {
+ updline(line)
+ } catch {
+ case exc: Throwable =>
+ println("Update line function failed, continuing anyway (probably old tlmgr)!")
+ }
}
}
stdOut.close()
} catch {
case exc: Throwable =>
stdOut.close()
+ // println("Exception in outputFn thread: " + exc + "\n")
errorBuffer.append(" Output thread: Exception: " + exc + "\n")
}
}
@@ -168,6 +174,7 @@ class TlmgrProcess(updout: Array[String] => Unit, upderr: String => Unit, updlin
} catch {
case exc: Throwable =>
stdErr.close()
+ // println("Exception in errorFn thread: " + exc + "\n")
errorBuffer.append(" Error thread: Exception: " + exc + "\n")
}
}