A package installation history tool for Sailfish OS.
Binary packages can be found at https://build.sailfishos.org/project/show/sailfishos:chum
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
536 lines
27 KiB
536 lines
27 KiB
/*
|
|
*
|
|
* Copyright 2022 Peter G. (nephros) <sailfish@nephros.org>
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*/
|
|
|
|
import QtQuick 2.6
|
|
import Sailfish.Silica 1.0
|
|
// for LauncherIcon
|
|
import Sailfish.Lipstick 1.0
|
|
// for LauncherModel, LauncherItem and friends
|
|
import org.nemomobile.lipstick 0.1
|
|
|
|
Page {
|
|
id: page
|
|
|
|
allowedOrientations: Orientation.All
|
|
|
|
property bool unclutter: false
|
|
property bool showLocal: true
|
|
property string historyfile: "/var/log/zypp/history"
|
|
|
|
Connections {
|
|
onStatusChanged: {
|
|
if (pageStack.busy) {
|
|
pageStack.busyChanged.connect(pushStatsPage)
|
|
} else {
|
|
pushStatsPage()
|
|
}
|
|
}
|
|
}
|
|
|
|
function pushStatsPage() {
|
|
if ( status === PageStatus.Active && pageStack.nextPage() === null && !pageStack.busy ) {
|
|
pageStack.pushAttached(statsPage);
|
|
pageStack.busyChanged.disconnect(pushStatsPage);
|
|
}
|
|
}
|
|
|
|
/*
|
|
onStatusChanged: {
|
|
if ( status === PageStatus.Active && !pageStack.busy && pageStack.nextPage() === null ) { pageStack.pushAttached(statsPage) }
|
|
}
|
|
*/
|
|
|
|
Component { id: statsPage; StatsPage{ } }
|
|
|
|
DockedPanel { id: detailInfo
|
|
z: 10 // this fixes transparency and focus problems
|
|
|
|
LauncherItem{ id: appInfo; filePath: "/usr/share/applications/" + detailInfo.appName + ".desktop" }
|
|
property string displayName: appInfo.isValid ? appInfo.title : ""
|
|
|
|
property var date
|
|
property var dateTime
|
|
property string appName
|
|
property string version
|
|
property string repo
|
|
property bool install
|
|
|
|
dock: Dock.Bottom
|
|
modal: true
|
|
animationDuration : 250
|
|
height: content.height
|
|
width: parent.width
|
|
Rectangle {
|
|
clip: true
|
|
anchors.fill: parent
|
|
anchors.centerIn: parent
|
|
radius: Theme.paddingSmall
|
|
//color: Theme.rgba(Theme.highlightDimmerColor, Theme.opacityOverlay)
|
|
//color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityOverlay)
|
|
//color: Theme.rgba(Theme.highlightDimmerFromColor(Theme.secondaryHighlightColor, Theme.colorScheme), Theme.opacityOverlay)
|
|
gradient: Gradient {
|
|
GradientStop { position: 0; color: Theme.rgba(Theme.highlightDimmerFromColor(Theme.secondaryHighlightColor, Theme.colorScheme), Theme.opacityOverlay) }
|
|
GradientStop { position: 2; color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityOverlay) }
|
|
}
|
|
|
|
}
|
|
Separator { anchors.verticalCenter: parent.top; anchors.horizontalCenter: parent.horizontalCenter;
|
|
width: parent.width ; height: Theme.paddingSmall
|
|
color: Theme.primaryColor;
|
|
horizontalAlignment: Qt.AlignHCenter
|
|
}
|
|
Row { id: content
|
|
anchors.centerIn: parent
|
|
width: parent.width
|
|
spacing: Theme.paddingMedium
|
|
padding: Theme.paddingLarge
|
|
LauncherIcon { id: icon
|
|
anchors.verticalCenter: detailCol.verticalCenter
|
|
width: size
|
|
icon: appInfo.isValid ? appInfo.iconId : "icon-m-file-rpm"
|
|
opacity: 1.0
|
|
size: Theme.iconSizeLarge
|
|
fillMode: Image.PreserveAspectFit
|
|
cache: true
|
|
smooth: false
|
|
asynchronous: true
|
|
}
|
|
Column { id: detailCol
|
|
width: parent.width - icon.width
|
|
Repeater { model: detailModel; delegate: Component { DetailItem{ width: detailCol.width; alignment: Qt.AlignLeft; visible: lbl.length > 0; label: lbl; value: val } } }
|
|
}
|
|
}
|
|
ListModel{ id: detailModel }
|
|
onExpandedChanged: updateModel()
|
|
function updateModel() {
|
|
detailModel.clear();
|
|
if (appInfo.isValid) {
|
|
detailModel.append( { "lbl": qsTr("Application"), "val": detailInfo.displayName });
|
|
}
|
|
detailModel.append( { "lbl": qsTr("Package"), "val": detailInfo.appName });
|
|
detailModel.append( { "lbl": qsTr("Version"), "val": detailInfo.version });
|
|
detailModel.append( { "lbl": detailInfo.install ? qsTr("Installed") : qsTr("Removed"),
|
|
"val": Format.formatDate(detailInfo.dateTime, Formatter.DateMedium)
|
|
+ " " + Format.formatDate(detailInfo.dateTime, Formatter.TimeValue)
|
|
});
|
|
detailModel.append( { "lbl": qsTr("Repository"), "val": detailInfo.repo ? detailInfo.repo : qsTr("n/a") } );
|
|
if (appInfo.isValid) {
|
|
detailModel.append( { "lbl": qsTr("Executes"), "val": appInfo.exec });
|
|
}
|
|
/*
|
|
if (appInfo.isValid) {
|
|
detailModel.append( { "lbl": qsTr("Sandboxed"), "val": detailInfo.appInfo.isSandboxed.toString() });
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
PullDownMenu { id: pdp
|
|
flickable: flick
|
|
MenuItem { text: qsTr("Refresh");
|
|
// refresh on delayedclick otherwise the bounce animation freezes while we reload
|
|
//onClicked: { appHistoryModel.clear(); view.forceLayout(); }
|
|
onClicked: { appHistoryModel.clear(); view.forceLayout(); view.model = null; }
|
|
onDelayedClick: { getHistory(page.historyfile,showLocal); view.model = appHistoryModel }
|
|
}
|
|
MenuItem { text: showLocal ? qsTr("Hide %1", "show/hide local menu option").arg(qsTr("Local Installs", "menu option parameter")) : qsTr("Show %1", "show/hide local menu option").arg(qsTr("Local Installs", "menu option parameter")) ;
|
|
// refresh on delayedclick otherwise the bounce animation freezes while we reload
|
|
onClicked: { showLocal = !showLocal; appHistoryModel.clear(); view.forceLayout(); view.model = null; }
|
|
onDelayedClick: { getHistory(page.historyfile,showLocal); view.model = appHistoryModel }
|
|
}
|
|
MenuItem { text: page.unclutter ? qsTr("Verbose Display", "menu option") : qsTr("Reduced Display", "menu option") ;
|
|
onClicked: page.unclutter = !page.unclutter
|
|
}
|
|
MenuItem { text: dateSearch.active ? qsTr("Hide search") : qsTr("Search by Date") ;
|
|
onClicked: {
|
|
dateSearch.active = !dateSearch.active
|
|
nameSearch.active = false
|
|
}
|
|
}
|
|
MenuItem { text: nameSearch.active ? qsTr("Hide search") : qsTr("Search by Name") ;
|
|
onClicked: {
|
|
nameSearch.active = !nameSearch.active
|
|
dateSearch.active = false
|
|
}
|
|
}
|
|
}
|
|
|
|
SilicaFlickable { id: flick
|
|
anchors.fill: parent
|
|
PageHeader { id: header ; title: qsTr("Install History") ; description: (appHistoryModel.count > 0) ? qsTr("%Ln event(s)", "very, very unlikely to have only one, still, plurals please!", appHistoryModel.count) : qsTr("Loading…")}
|
|
Column {
|
|
id: searchBar
|
|
anchors.top: header.bottom
|
|
width: parent.width
|
|
SearchField { id: dateSearch
|
|
active: false
|
|
width: parent.width - Theme.horizontalPageMargin
|
|
readOnly: true
|
|
placeholderText: view.jumpDate != null ? view.jumpDate.toISOString().substr(0,10) : qsTr("Date")
|
|
onClicked: {
|
|
var dialog = pageStack.push(datePicker)
|
|
dialog.accepted.connect( function() { view.jumpDate = dialog.date; })
|
|
}
|
|
Separator { anchors.verticalCenter: parent.bottom; width: parent.width; color: Theme.primaryColor;}
|
|
}
|
|
SearchField { id: nameSearch
|
|
active: false
|
|
width: parent.width - Theme.horizontalPageMargin
|
|
placeholderText: qsTr("Name")
|
|
inputMethodHints: Qt.ImhNoAutoUppercase
|
|
EnterKey.enabled: text.length > 3
|
|
EnterKey.iconSource: "image://theme/icon-m-enter-next"
|
|
EnterKey.onClicked: view.findNames(text)
|
|
onVisibleChanged: { focus = visible }
|
|
Separator { anchors.verticalCenter: parent.bottom; width: parent.width; color: Theme.primaryColor;}
|
|
}
|
|
}
|
|
|
|
SilicaListView { id: view
|
|
anchors.top: searchBar.bottom
|
|
height: parent.height - (header.height + searchBar.height)
|
|
width: parent.width - Theme.horizontalPageMargin
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
cacheBuffer: page.height * 2
|
|
populate: Transition { NumberAnimation { properties: "y"; from: 100; duration: 600 } }
|
|
clip: true
|
|
spacing: Theme.paddingMedium
|
|
model: appHistoryModel
|
|
section {
|
|
labelPositioning: page.unclutter ? ViewSection.CurrentLabelAtStart : ViewSection.InlineLabels
|
|
property: "date"
|
|
delegate: SectionHeader {
|
|
text: Format.formatDate(section, Formatter.TimepointSectionRelative)
|
|
font.capitalization: Font.Capitalize
|
|
}
|
|
}
|
|
|
|
property var jumpDate: null
|
|
onJumpDateChanged: if (jumpDate != null) { view.jumpTo(jumpDate) }
|
|
/*
|
|
* TODO: make this smarter:
|
|
*
|
|
* maybe have a separate object containing a search index with only the first occurrence of each date
|
|
* filled on first use and re-used
|
|
*/
|
|
function jumpTo(jumpDate) {
|
|
console.time("Jump search took: ");
|
|
var pos = findIndex(appHistoryModel, function(item) { return item.date.match("^" + jumpDate.toISOString().substr(0,10)) });
|
|
if (pos) {
|
|
positionViewAtIndex(pos, ListView.Beginning);
|
|
currentIndex = pos;
|
|
return;
|
|
} else {
|
|
var searchDate = jumpDate;
|
|
for (i=Number(jumpDate.toISOString().substr(-2)); i > 0; i--) {
|
|
searchDate = searchDate - 864e5; // remove 86,400,000 milliseconds == one day
|
|
pos = find(appHistoryModel, function(item) { return item.date.match("^" + jumpDate.toISOString().substr(0,10)) });
|
|
if (pos) {
|
|
positionViewAtIndex(pos, ListView.Beginning);
|
|
currentIndex = pos;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
console.timeEnd("Jump search took: ");
|
|
}
|
|
|
|
function findNames(name) {
|
|
console.time("Name search took: ");
|
|
var pos = findIndex(appHistoryModel, function(item) { return item.appName.match(name) });
|
|
positionViewAtIndex(pos, ListView.Beginning);
|
|
currentIndex = pos;
|
|
console.timeEnd("Name search took: ");
|
|
}
|
|
/* find something, return index */
|
|
function findIndex(model, criteria) {
|
|
for(var i = ((currentIndex > 0) ? currentIndex+1 : 0); i < model.count; ++i) if (criteria(model.get(i))) return i
|
|
return -1
|
|
}
|
|
|
|
/* find something, return object */
|
|
function find(model, criteria) {
|
|
for(var i = 0; i < model.count; ++i) if (criteria(model.get(i))) return model.get(i)
|
|
return null
|
|
}
|
|
|
|
highlight: highlightBar
|
|
currentIndex: -1
|
|
delegate: Component { id: historyItem
|
|
ListItem { id: li
|
|
width: ListView.view.width
|
|
contentHeight: packagerow.height
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
property bool install: (action == "install")
|
|
property bool unclutter: page.unclutter
|
|
menu: Component { ContextMenu {
|
|
//MenuItem { enabled: false; text: qsTr("Search in %1").arg(qsTr("Jolla Store")) ; onClicked: Qt.openUrlExternally("" + appName) }
|
|
MenuItem { enabled: repoType == "openrepos" ; text: qsTr("Search on %1").arg("OpenRepos.") ; onClicked: Qt.openUrlExternally("https://openrepos.net/search/node/" + appName) }
|
|
MenuItem { enabled: repoType == "chum" ; text: qsTr("Search on %1").arg("SailfishOS:Chum") ; onClicked: Qt.openUrlExternally("https://build.sailfishos.org/package/show/sailfishos:chum/" + appName) }
|
|
}
|
|
}
|
|
onClicked: {
|
|
detailInfo.appName = appName;
|
|
detailInfo.version = version;
|
|
detailInfo.repo = repo;
|
|
detailInfo.date = date;
|
|
detailInfo.dateTime = dateTime;
|
|
detailInfo.install = install;
|
|
detailInfo.show();
|
|
}
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
anchors.centerIn: parent
|
|
radius: Theme.paddingSmall
|
|
color: install ? Theme.rgba(Theme.secondaryColor, 0.05) : Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityFaint)
|
|
}
|
|
Icon { id: plusicon;
|
|
anchors.left: parent.left; anchors.verticalCenter: parent.verticalCenter
|
|
height: unclutter ? Theme.iconSizeSmall : Theme.iconSizeMedium
|
|
source: install ? "image://theme/icon-m-add?" + Theme.highlightFromColor(Theme.presenceColor(Theme.PresenceAvailable), Theme.colorScheme) : "image://theme/icon-m-remove?" + Theme.highlightFromColor(Theme.presenceColor(Theme.PresenceAway), Theme.colorScheme)
|
|
fillMode: Image.PreserveAspectFit
|
|
}
|
|
Row { id: packagerow
|
|
anchors.verticalCenter: plusicon.verticalCenter
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.left: plusicon.right
|
|
anchors.margins: Theme.paddingSmall
|
|
width: parent.width - plusicon.width
|
|
Column { id: col
|
|
width: parent.width
|
|
Row { spacing: Theme.paddingSmall
|
|
visible: li.unclutter
|
|
// name, version: uncluttered
|
|
Label{ visible: li.unclutter;
|
|
font.pixelSize: Theme.fontSizeSmall; color: Theme.secondaryColor;
|
|
horizontalAlignment: install ? Text.AlignLeft : Text.AlignRight
|
|
width: Math.min(implicitWidth, col.width * 2/3);
|
|
maximumLineCount: 1; truncationMode: TruncationMode.Elide; elide: Text.ElideMiddle;
|
|
text: page.isLandscape ?
|
|
Format.formatDate(dateTime, Formatter.DateMedium) + " " + Format.formatDate(dateTime, Formatter.TimeValue)
|
|
: Format.formatDate(dateTime, Formatter.DateMediumWithoutYear) + " " + Format.formatDate(dateTime, Formatter.TimeValue)
|
|
}
|
|
Label{ text: appName ; maximumLineCount: 1; truncationMode: TruncationMode.Elide; elide: Text.ElideMiddle; horizontalAlignment: install ? Text.AlignLeft : Text.AlignRight; color: install ? Theme.highlightColor : Theme.primaryColor }
|
|
Label{ visible: page.isLandscape; text: version ; maximumLineCount: 1; truncationMode: TruncationMode.Elide; elide: Text.ElideLeft; horizontalAlignment: install ? Text.AlignLeft : Text.AlignRight; color: install ? Theme.secondaryHighlightColor : Theme.secondaryColor}
|
|
Label{ visible: ( install && page.isLandscape)
|
|
text: repo; color: Theme.highlightBackgroundColor; font.pixelSize: Theme.fontSizeSmall}
|
|
}
|
|
Row { spacing: Theme.paddingSmall
|
|
visible: !li.unclutter
|
|
// name, version: default
|
|
Label{ visible: li.unclutter;
|
|
font.pixelSize: Theme.fontSizeSmall; color: Theme.secondaryColor;
|
|
horizontalAlignment: install ? Text.AlignLeft : Text.AlignRight
|
|
width: Math.min(implicitWidth, col.width * 2/3);
|
|
maximumLineCount: 1; truncationMode: TruncationMode.Elide; elide: Text.ElideMiddle;
|
|
//text: Format.formatDate(date, Formatter.DateMedium) + " " + Format.formatDate(dateTime, Formatter.TimeValue)
|
|
text: page.isLandscape ?
|
|
Format.formatDate(dateTime, Formatter.DateMedium) + " " + Format.formatDate(dateTime, Formatter.TimeValue)
|
|
: Format.formatDate(dateTime, Formatter.DateMediumWithoutYear) + " " + Format.formatDate(dateTime, Formatter.TimeValue)
|
|
}
|
|
Label{ text: appName ; maximumLineCount: 1; truncationMode: TruncationMode.Elide; elide: Text.ElideMiddle; horizontalAlignment: install ? Text.AlignLeft : Text.AlignRight; color: install ? Theme.highlightColor : Theme.primaryColor }
|
|
Label{ visible: !li.unclutter; text: version ; maximumLineCount: 1; truncationMode: TruncationMode.Elide; elide: Text.ElideLeft; horizontalAlignment: install ? Text.AlignLeft : Text.AlignRight; color: install ? Theme.secondaryHighlightColor : Theme.secondaryColor}
|
|
}
|
|
Row { spacing: Theme.paddingSmall
|
|
visible: !li.unclutter
|
|
// date
|
|
Label{ font.pixelSize: Theme.fontSizeSmall; color: Theme.secondaryColor;
|
|
horizontalAlignment: install ? Text.AlignLeft : Text.AlignRight
|
|
width: Math.min(implicitWidth, col.width * 2/3);
|
|
maximumLineCount: 1; truncationMode: TruncationMode.Elide; elide: Text.ElideMiddle;
|
|
//text: Format.formatDate(date, Formatter.DateMedium) + " " + Format.formatDate(dateTime, Formatter.TimeValue)
|
|
//text: Format.formatDate(date, Formatter.DateMediumWithoutYear) + " " + Format.formatDate(dateTime, Formatter.TimeValue)
|
|
text: Format.formatDate(dateTime, Formatter.DateMediumWithoutYear) + " " + Format.formatDate(dateTime, Formatter.TimeValue)
|
|
}
|
|
// repo
|
|
Label{ visible: ( install && !li.unclutter )
|
|
text: repoName ; horizontalAlignment: install ? Text.AlignLeft : Text.AlignRight; color: Theme.highlightBackgroundColor; font.pixelSize: Theme.fontSizeSmall}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
VerticalScrollDecorator {}
|
|
}
|
|
}
|
|
|
|
ListModel { id: appHistoryModel; Component.onCompleted: { getHistory(page.historyfile,showLocal); } }
|
|
|
|
Component{ id: datePicker; DatePickerDialog {} }
|
|
|
|
Component { id: highlightBar
|
|
Rectangle {
|
|
color: Theme.rgba(Theme.highlightBackgroundColor, Theme.opacityFaint);
|
|
border.color: Theme.highlightBackgroundColor
|
|
radius: Theme.paddingSmall
|
|
}
|
|
}
|
|
|
|
/* ----- functions ----- */
|
|
|
|
/* load zypper history log file */
|
|
function getHistory(fn,filter) {
|
|
console.assert((typeof fn !== "undefined"), "Called without filename");
|
|
console.info("Loading history from " + fn);
|
|
console.time("File request took");
|
|
const query = Qt.resolvedUrl("file://" + fn);
|
|
var r = new XMLHttpRequest()
|
|
r.open('GET', query);
|
|
r.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
|
r.send();
|
|
|
|
r.onreadystatechange = function(event) {
|
|
if (r.readyState == XMLHttpRequest.DONE) {
|
|
fillModel(r.response.split("\n").reverse(),filter);
|
|
console.timeEnd("File request took");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* helper to reduce payload */
|
|
function filterData(data) {
|
|
// lines have the format:
|
|
// 20xx-mm-dd HH:MM:SS|install
|
|
// 20xx-mm-dd HH:MM:SS|remove
|
|
// ..................^17
|
|
// everything else is not interesting
|
|
const re = /^20.{17}(\|install|\|remove).*$/;
|
|
return (re.test(data)) ? true : false;
|
|
}
|
|
function filterLocal(data) {
|
|
const re = /\|PK_TMP_DIR\|/ // pkcon
|
|
const re = /\|_tmpRPMcache_\|/ // zypper
|
|
return (!re.test(data)) ? true : false;
|
|
}
|
|
|
|
/* populate ListModel from payload */
|
|
function fillModel(a,filter) {
|
|
console.time("List loaded in");
|
|
console.time("Filtering took");
|
|
const data = a.filter(filterData);
|
|
if (!filter)
|
|
const data = data.filter(filterLocal);
|
|
console.timeEnd("Filtering took");
|
|
console.debug("Filtered Lines: " + data.length + "/" + a.length);
|
|
// performance: compile regexp and define and loop variables
|
|
// outside the loop
|
|
// also, looks oldschool to declare all vars at the top.
|
|
const isOpenrepos = /^openrepos-/
|
|
//const jollarepos = /(adaptation0 adaptation1 aliendalvik apps customer-jolla jolla sailfish-eas store xt9)/
|
|
const line;
|
|
const dt;
|
|
const d;
|
|
const t;
|
|
const date;
|
|
const dateTime;
|
|
const repo;
|
|
const repotype = "other";
|
|
const reponame = null;
|
|
const element = {};
|
|
data.forEach(function(r){
|
|
line = r.split("|");
|
|
|
|
// zypper stores local time at the time of the event.
|
|
// see https://codeberg.org/nephros/install-history/issues/16
|
|
dt = line[0].split(" ");
|
|
d = dt[0].split("-"); t = dt[1].split(":");
|
|
// months are counted from 0-11, so do a d[1] - 1
|
|
date = new Date( d[0], d[1] - 1, d[2], 0, 0, 0, 0).toISOString();
|
|
dateTime = new Date( d[0], d[1] - 1, d[2], t[0], t[1], t[2], 0);
|
|
|
|
/* assign pretty names:
|
|
*
|
|
grep install /var/log/zypp/history |grep -v PK_TMP_DIR | awk -F\| '{print $7}'| sort -u | grep -v openrepos
|
|
|
|
adaptation0
|
|
adaptation1
|
|
aliendalvik
|
|
customer-jolla
|
|
harbour-storeman-obs
|
|
mentaljam-obs
|
|
sailfish-eas
|
|
sailfishos-chum
|
|
sailfishos-chum-testing
|
|
store
|
|
xt9
|
|
*/
|
|
repo = line[6];
|
|
reponame = repo;
|
|
if ( (repo === "PK_TMP_DIR") || (repo === "_tmpRPMcache_") ) {
|
|
repo=qsTr("local", "short name for the 'local' repo");
|
|
reponame=qsTr("Local Installs", "name for the 'local' repo");
|
|
repotype="local";
|
|
} else if (repo === "store") {
|
|
reponame=qsTr("Jolla Store", "name for the jolla store repo");
|
|
repotype="jolla";
|
|
} else if (repo === "jolla") {
|
|
reponame=qsTr("Jolla System", "name for the jolla jolla repo");
|
|
repotype="jolla";
|
|
} else if (repo === "aliendalvik") {
|
|
reponame=qsTr("Android App Support", "name for the android support repo");
|
|
repotype="jolla";
|
|
} else if (repo === "apps") {
|
|
reponame=qsTr("Jolla Applications", "name for the jolla apps repo");
|
|
repotype="jolla";
|
|
} else if (repo === "sailfish-eas") {
|
|
reponame=qsTr("Exchange Feature", "name for the jolla feature repo");
|
|
repotype="jolla";
|
|
} else if (repo === "xt9") {
|
|
reponame=qsTr("XT9 Feature", "name for the jolla feature repo");
|
|
repotype="jolla";
|
|
} else if (repo === "customer-jolla") {
|
|
reponame=qsTr("Jolla Feature", "name for the jolla customer repo");
|
|
repotype="jolla";
|
|
} else if (repo === "adaptation0") {
|
|
reponame=qsTr("Device Adaptation", "name for the jolla adaptation0 repo");
|
|
repotype="jolla";
|
|
} else if (repo === "adaptation1") {
|
|
reponame=qsTr("Device Adaptation", "name for the jolla adaptation1 repo");
|
|
repotype="jolla";
|
|
} else if ( (repo === "mentaljam-obs") || (repo === "harbour-storeman-obs") ) {
|
|
reponame=qsTr("Storeman", "name for the storeman repo");
|
|
} else if (repo === "sailfishos-chum") {
|
|
reponame=qsTr("SailfishOS:Chum", "name for the chum repo");
|
|
repotype="chum";
|
|
} else if (repo === "sailfishos-chum-testing") {
|
|
reponame=qsTr("SailfishOS:Chum Testing", "name for the chum testing repo");
|
|
repotype="chum";
|
|
} else if (repo === "nubecula-mls-offline-repo") {
|
|
reponame=qsTr("MLS", "name for the Nubecula Offline MLS repo");
|
|
} else if ( isOpenrepos.test(repo) ) {
|
|
reponame= qsTr("OpenRepos: %1", "prefix for a openrepos repo").arg(repo.replace("openrepos-", ""));
|
|
repotype="openrepos";
|
|
}
|
|
element = {
|
|
"date": date,
|
|
"dateTime": dateTime,
|
|
"action": line[1].trim(),
|
|
"appName": line[2],
|
|
"version": line[3],
|
|
"repo": repo,
|
|
"repoName": reponame,
|
|
"repoType": repotype,
|
|
}
|
|
appHistoryModel.append(element);
|
|
}); // foreach func end
|
|
console.timeEnd("List loaded in");
|
|
}
|
|
}
|
|
|
|
// vim: expandtab ts=4 st=4 sw=4 filetype=javascript
|
|
|