mirror of
https://github.com/nomic-ai/gpt4all
synced 2024-11-10 01:10:35 +00:00
new UI fixes, part 5 (#2485)
additional new ui changes, part 5 (#2485) Signed-off-by: Jared Van Bortel <jared@nomic.ai>
This commit is contained in:
parent
22396a6fa1
commit
a191844a3f
@ -1493,7 +1493,7 @@ void Database::start()
|
||||
} else if (!initDb(modelPath, oldCollections)) {
|
||||
m_databaseValid = false;
|
||||
} else {
|
||||
//cleanDB();
|
||||
cleanDB();
|
||||
addCurrentFolders();
|
||||
}
|
||||
|
||||
@ -2118,7 +2118,8 @@ void Database::changeFileExtensions(const QStringList &extensions)
|
||||
|
||||
m_scannedFileExtensions = extensions;
|
||||
|
||||
cleanDB();
|
||||
if (cleanDB())
|
||||
updateCollectionStatistics();
|
||||
|
||||
QSqlQuery q(m_db);
|
||||
QList<CollectionItem> collections;
|
||||
|
@ -413,7 +413,7 @@ Window {
|
||||
|
||||
ColorOverlay {
|
||||
id: antennaColored
|
||||
visible: ModelList.installedModels.count !== 0 && (currentChat.isServer || currentChat.modelInfo.isOnline || MySettings.networkIsActive)
|
||||
visible: ModelList.selectableModels.count !== 0 && (currentChat.isServer || currentChat.modelInfo.isOnline || MySettings.networkIsActive)
|
||||
anchors.fill: antennaImage
|
||||
source: antennaImage
|
||||
color: theme.styledTextColor
|
||||
|
@ -312,6 +312,7 @@
|
||||
"filename": "all-MiniLM-L6-v2.gguf2.f16.gguf",
|
||||
"filesize": "45949216",
|
||||
"requires": "2.7.4",
|
||||
"removedIn": "3.0.0",
|
||||
"ramrequired": "1",
|
||||
"parameters": "40 million",
|
||||
"quant": "f16",
|
||||
|
@ -367,8 +367,9 @@ QVariantMap ModelInfo::getFields() const
|
||||
};
|
||||
}
|
||||
|
||||
InstalledModels::InstalledModels(QObject *parent)
|
||||
InstalledModels::InstalledModels(QObject *parent, bool selectable)
|
||||
: QSortFilterProxyModel(parent)
|
||||
, m_selectable(selectable)
|
||||
{
|
||||
connect(this, &InstalledModels::rowsInserted, this, &InstalledModels::countChanged);
|
||||
connect(this, &InstalledModels::rowsRemoved, this, &InstalledModels::countChanged);
|
||||
@ -379,11 +380,15 @@ InstalledModels::InstalledModels(QObject *parent)
|
||||
bool InstalledModels::filterAcceptsRow(int sourceRow,
|
||||
const QModelIndex &sourceParent) const
|
||||
{
|
||||
/* TODO(jared): We should list incomplete models alongside installed models on the
|
||||
* Models page. Simply replacing isDownloading with isIncomplete here doesn't work for
|
||||
* some reason - the models show up as something else. */
|
||||
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
bool isInstalled = sourceModel()->data(index, ModelList::InstalledRole).toBool();
|
||||
bool isDownloading = sourceModel()->data(index, ModelList::DownloadingRole).toBool();
|
||||
bool isEmbeddingModel = sourceModel()->data(index, ModelList::IsEmbeddingModelRole).toBool();
|
||||
// list installed chat models
|
||||
return isInstalled && !isEmbeddingModel;
|
||||
return (isInstalled || (!m_selectable && isDownloading)) && !isEmbeddingModel;
|
||||
}
|
||||
|
||||
DownloadableModels::DownloadableModels(QObject *parent)
|
||||
@ -403,11 +408,9 @@ bool DownloadableModels::filterAcceptsRow(int sourceRow,
|
||||
// FIXME We can eliminate the 'expanded' code as the UI no longer uses this
|
||||
bool withinLimit = sourceRow < (m_expanded ? sourceModel()->rowCount() : m_limit);
|
||||
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||
bool isDownloadable = !sourceModel()->data(index, ModelList::DescriptionRole).toString().isEmpty();
|
||||
bool isInstalled = sourceModel()->data(index, ModelList::InstalledRole).toBool();
|
||||
bool isIncomplete = sourceModel()->data(index, ModelList::IncompleteRole).toBool();
|
||||
bool hasDescription = !sourceModel()->data(index, ModelList::DescriptionRole).toString().isEmpty();
|
||||
bool isClone = sourceModel()->data(index, ModelList::IsCloneRole).toBool();
|
||||
return withinLimit && !isClone && !isInstalled && (isDownloadable || isIncomplete);
|
||||
return withinLimit && hasDescription && !isClone;
|
||||
}
|
||||
|
||||
int DownloadableModels::count() const
|
||||
@ -446,6 +449,7 @@ ModelList *ModelList::globalInstance()
|
||||
ModelList::ModelList()
|
||||
: QAbstractListModel(nullptr)
|
||||
, m_installedModels(new InstalledModels(this))
|
||||
, m_selectableModels(new InstalledModels(this, /*selectable*/ true))
|
||||
, m_downloadableModels(new DownloadableModels(this))
|
||||
, m_asyncModelRequestOngoing(false)
|
||||
, m_discoverLimit(20)
|
||||
@ -456,6 +460,7 @@ ModelList::ModelList()
|
||||
, m_discoverInProgress(false)
|
||||
{
|
||||
m_installedModels->setSourceModel(this);
|
||||
m_selectableModels->setSourceModel(this);
|
||||
m_downloadableModels->setSourceModel(this);
|
||||
|
||||
connect(MySettings::globalInstance(), &MySettings::modelPathChanged, this, &ModelList::updateModelsFromDirectory);
|
||||
|
@ -208,7 +208,7 @@ class InstalledModels : public QSortFilterProxyModel
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
public:
|
||||
explicit InstalledModels(QObject *parent);
|
||||
explicit InstalledModels(QObject *parent, bool selectable = false);
|
||||
int count() const { return rowCount(); }
|
||||
|
||||
Q_SIGNALS:
|
||||
@ -216,6 +216,9 @@ Q_SIGNALS:
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
|
||||
|
||||
private:
|
||||
bool m_selectable;
|
||||
};
|
||||
|
||||
class DownloadableModels : public QSortFilterProxyModel
|
||||
@ -252,6 +255,7 @@ class ModelList : public QAbstractListModel
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(InstalledModels* installedModels READ installedModels NOTIFY installedModelsChanged)
|
||||
Q_PROPERTY(InstalledModels* selectableModels READ selectableModels NOTIFY selectableModelsChanged)
|
||||
Q_PROPERTY(DownloadableModels* downloadableModels READ downloadableModels NOTIFY downloadableModelsChanged)
|
||||
Q_PROPERTY(QList<QString> userDefaultModelList READ userDefaultModelList NOTIFY userDefaultModelListChanged)
|
||||
Q_PROPERTY(bool asyncModelRequestOngoing READ asyncModelRequestOngoing NOTIFY asyncModelRequestOngoingChanged)
|
||||
@ -396,6 +400,7 @@ public:
|
||||
const QList<QString> userDefaultModelList() const;
|
||||
|
||||
InstalledModels *installedModels() const { return m_installedModels; }
|
||||
InstalledModels *selectableModels() const { return m_selectableModels; }
|
||||
DownloadableModels *downloadableModels() const { return m_downloadableModels; }
|
||||
|
||||
static inline QString toFileSize(quint64 sz) {
|
||||
@ -433,6 +438,7 @@ public:
|
||||
Q_SIGNALS:
|
||||
void countChanged();
|
||||
void installedModelsChanged();
|
||||
void selectableModelsChanged();
|
||||
void downloadableModelsChanged();
|
||||
void userDefaultModelListChanged();
|
||||
void asyncModelRequestOngoingChanged();
|
||||
@ -471,6 +477,7 @@ private:
|
||||
mutable QMutex m_mutex;
|
||||
QNetworkAccessManager m_networkManager;
|
||||
InstalledModels *m_installedModels;
|
||||
InstalledModels *m_selectableModels;
|
||||
DownloadableModels *m_downloadableModels;
|
||||
QList<ModelInfo*> m_models;
|
||||
QHash<QString, ModelInfo*> m_modelMap;
|
||||
|
@ -365,7 +365,12 @@ Rectangle {
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Description")
|
||||
Accessible.description: qsTr("File description")
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
onLinkActivated: function(link) { Qt.openUrlExternally(link); }
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton // pass clicks to parent
|
||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME Need to overhaul design here which must take into account
|
||||
@ -418,7 +423,7 @@ Rectangle {
|
||||
Layout.minimumWidth: 200
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
visible: installed || downloadError !== ""
|
||||
visible: !isDownloading && (installed || isIncomplete)
|
||||
Accessible.description: qsTr("Remove model from filesystem")
|
||||
onClicked: {
|
||||
Download.removeModel(filename);
|
||||
|
@ -242,8 +242,8 @@ Rectangle {
|
||||
enabled: !currentChat.isServer
|
||||
&& !currentChat.trySwitchContextInProgress
|
||||
&& !currentChat.isCurrentlyLoading
|
||||
&& ModelList.installedModels.count !== 0
|
||||
model: ModelList.installedModels
|
||||
&& ModelList.selectableModels.count !== 0
|
||||
model: ModelList.selectableModels
|
||||
valueRole: "id"
|
||||
textRole: "name"
|
||||
|
||||
@ -297,7 +297,7 @@ Rectangle {
|
||||
return 25
|
||||
}
|
||||
text: {
|
||||
if (ModelList.installedModels.count === 0)
|
||||
if (ModelList.selectableModels.count === 0)
|
||||
return qsTr("No model installed...")
|
||||
if (currentChat.modelLoadingError !== "")
|
||||
return qsTr("Model loading error...")
|
||||
@ -602,10 +602,10 @@ Rectangle {
|
||||
id: homePage
|
||||
color: "transparent"
|
||||
anchors.fill: parent
|
||||
visible: !currentChat.isModelLoaded && (ModelList.installedModels.count === 0 || currentModelName() === "") && !currentChat.isServer
|
||||
visible: !currentChat.isModelLoaded && (ModelList.selectableModels.count === 0 || currentModelName() === "") && !currentChat.isServer
|
||||
|
||||
ColumnLayout {
|
||||
visible: ModelList.installedModels.count !== 0
|
||||
visible: ModelList.selectableModels.count !== 0
|
||||
id: modelInstalledLabel
|
||||
anchors.centerIn: parent
|
||||
spacing: 0
|
||||
@ -637,7 +637,7 @@ Rectangle {
|
||||
|
||||
MyButton {
|
||||
id: loadDefaultModelButton
|
||||
visible: ModelList.installedModels.count !== 0
|
||||
visible: ModelList.selectableModels.count !== 0
|
||||
anchors.top: modelInstalledLabel.bottom
|
||||
anchors.topMargin: 50
|
||||
anchors.horizontalCenter: modelInstalledLabel.horizontalCenter
|
||||
@ -683,7 +683,7 @@ Rectangle {
|
||||
|
||||
ColumnLayout {
|
||||
id: noModelInstalledLabel
|
||||
visible: ModelList.installedModels.count === 0
|
||||
visible: ModelList.selectableModels.count === 0
|
||||
anchors.centerIn: parent
|
||||
spacing: 0
|
||||
|
||||
@ -704,7 +704,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
MyButton {
|
||||
visible: ModelList.installedModels.count === 0
|
||||
visible: ModelList.selectableModels.count === 0
|
||||
anchors.top: noModelInstalledLabel.bottom
|
||||
anchors.topMargin: 50
|
||||
anchors.horizontalCenter: noModelInstalledLabel.horizontalCenter
|
||||
@ -721,7 +721,7 @@ Rectangle {
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
visible: ModelList.installedModels.count !== 0 && chatModel.count !== 0
|
||||
visible: ModelList.selectableModels.count !== 0 && chatModel.count !== 0
|
||||
ListView {
|
||||
id: listView
|
||||
Layout.maximumWidth: 1280
|
||||
@ -1047,10 +1047,9 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
TextArea {
|
||||
text: consolidatedSources.length + " " + qsTr("Sources")
|
||||
Text {
|
||||
text: qsTr("%1 Sources").arg(consolidatedSources.length)
|
||||
padding: 0
|
||||
readOnly: true
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
font.bold: true
|
||||
color: theme.styledTextColor
|
||||
@ -1095,6 +1094,7 @@ Rectangle {
|
||||
id: sourcesLayout
|
||||
Layout.row: 3
|
||||
Layout.column: 1
|
||||
Layout.topMargin: 5
|
||||
visible: consolidatedSources.length !== 0 && MySettings.localDocsShowReferences && (!currentResponse || !currentChat.responseInProgress)
|
||||
clip: true
|
||||
Layout.fillWidth: true
|
||||
@ -1126,7 +1126,6 @@ Rectangle {
|
||||
|
||||
Flow {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 5
|
||||
spacing: 10
|
||||
visible: consolidatedSources.length !== 0
|
||||
Repeater {
|
||||
@ -1397,7 +1396,7 @@ Rectangle {
|
||||
|
||||
RectangularGlow {
|
||||
id: effect
|
||||
visible: !currentChat.isServer && ModelList.installedModels.count !== 0
|
||||
visible: !currentChat.isServer && ModelList.selectableModels.count !== 0
|
||||
anchors.fill: textInputView
|
||||
glowRadius: 50
|
||||
spread: 0
|
||||
@ -1415,7 +1414,7 @@ Rectangle {
|
||||
anchors.leftMargin: Math.max((parent.width - 1310) / 2, 30)
|
||||
anchors.rightMargin: Math.max((parent.width - 1310) / 2, 30)
|
||||
height: Math.min(contentHeight, 200)
|
||||
visible: !currentChat.isServer && ModelList.installedModels.count !== 0
|
||||
visible: !currentChat.isServer && ModelList.selectableModels.count !== 0
|
||||
MyTextArea {
|
||||
id: textInput
|
||||
color: theme.textColor
|
||||
@ -1509,7 +1508,7 @@ Rectangle {
|
||||
anchors.rightMargin: 15
|
||||
width: 30
|
||||
height: 30
|
||||
visible: !currentChat.isServer && ModelList.installedModels.count !== 0
|
||||
visible: !currentChat.isServer && ModelList.selectableModels.count !== 0
|
||||
enabled: !currentChat.responseInProgress
|
||||
source: "qrc:/gpt4all/icons/send_message.svg"
|
||||
Accessible.name: qsTr("Send message")
|
||||
|
@ -136,7 +136,7 @@ Rectangle {
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
text: qsTr("Chat privately with local files using on-device Large Language Models (LLMs). Keeps data private and secure. Best results with Llama 3 Instruct.")
|
||||
text: qsTr("Select a collection to make it available to the chat model.")
|
||||
font.pixelSize: theme.fontSizeLarger
|
||||
wrapMode: Text.WordWrap
|
||||
elide: Text.ElideRight
|
||||
|
@ -53,7 +53,7 @@ Rectangle {
|
||||
|
||||
Text {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
text: qsTr("the privacy-first LLM chat application")
|
||||
text: qsTr("The privacy-first LLM chat application")
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
color: theme.titleInfoTextColor
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ MySettingsTab {
|
||||
columns: 3
|
||||
rowSpacing: 10
|
||||
columnSpacing: 10
|
||||
enabled: ModelList.installedModels.count !== 0
|
||||
enabled: ModelList.selectableModels.count !== 0
|
||||
|
||||
property var currentModelName: comboBox.currentText
|
||||
property var currentModelId: comboBox.currentValue
|
||||
@ -43,7 +43,7 @@ MySettingsTab {
|
||||
MyComboBox {
|
||||
id: comboBox
|
||||
Layout.fillWidth: true
|
||||
model: ModelList.installedModels
|
||||
model: ModelList.selectableModels
|
||||
valueRole: "id"
|
||||
textRole: "name"
|
||||
currentIndex: {
|
||||
|
@ -82,7 +82,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
Text {
|
||||
text: qsTr("Locally installed large language models")
|
||||
text: qsTr("Locally installed chat models")
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
color: theme.titleInfoTextColor
|
||||
}
|
||||
@ -150,20 +150,240 @@ Rectangle {
|
||||
color: theme.dividerColor
|
||||
}
|
||||
|
||||
Text {
|
||||
id: descriptionText
|
||||
text: description
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
Layout.row: 1
|
||||
RowLayout {
|
||||
Layout.topMargin: 10
|
||||
wrapMode: Text.WordWrap
|
||||
textFormat: Text.StyledText
|
||||
color: theme.textColor
|
||||
linkColor: theme.textColor
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Description")
|
||||
Accessible.description: qsTr("File description")
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
Layout.fillWidth: true
|
||||
Text {
|
||||
id: descriptionText
|
||||
text: description
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
textFormat: Text.StyledText
|
||||
color: theme.textColor
|
||||
linkColor: theme.textColor
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Description")
|
||||
Accessible.description: qsTr("File description")
|
||||
onLinkActivated: function(link) { Qt.openUrlExternally(link); }
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton // pass clicks to parent
|
||||
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: actionBox
|
||||
width: childrenRect.width + 20
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: theme.dividerColor
|
||||
radius: 10
|
||||
Layout.rightMargin: 20
|
||||
Layout.bottomMargin: 20
|
||||
Layout.minimumHeight: childrenRect.height + 20
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignTop
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
MySettingsButton {
|
||||
id: downloadButton
|
||||
text: isDownloading ? qsTr("Cancel") : qsTr("Resume")
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
Layout.topMargin: 20
|
||||
Layout.leftMargin: 20
|
||||
Layout.minimumWidth: 200
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
visible: (isDownloading || isIncomplete) && downloadError === "" && !isOnline && !calcHash
|
||||
Accessible.description: qsTr("Stop/restart/start the download")
|
||||
onClicked: {
|
||||
if (!isDownloading) {
|
||||
Download.downloadModel(filename);
|
||||
} else {
|
||||
Download.cancelDownload(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MySettingsDestructiveButton {
|
||||
id: removeButton
|
||||
text: qsTr("Remove")
|
||||
Layout.topMargin: 20
|
||||
Layout.leftMargin: 20
|
||||
Layout.minimumWidth: 200
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
visible: !isDownloading && (installed || isIncomplete)
|
||||
Accessible.description: qsTr("Remove model from filesystem")
|
||||
onClicked: {
|
||||
Download.removeModel(filename);
|
||||
}
|
||||
}
|
||||
|
||||
MySettingsButton {
|
||||
id: installButton
|
||||
visible: !installed && isOnline
|
||||
Layout.topMargin: 20
|
||||
Layout.leftMargin: 20
|
||||
Layout.minimumWidth: 200
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
text: qsTr("Install")
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
onClicked: {
|
||||
if (apiKey.text === "")
|
||||
apiKey.showError();
|
||||
else
|
||||
Download.installModel(filename, apiKey.text);
|
||||
}
|
||||
Accessible.role: Accessible.Button
|
||||
Accessible.name: qsTr("Install")
|
||||
Accessible.description: qsTr("Install online model")
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: 0
|
||||
Label {
|
||||
Layout.topMargin: 20
|
||||
Layout.leftMargin: 20
|
||||
visible: downloadError !== ""
|
||||
textFormat: Text.StyledText
|
||||
text: "<strong><font size=\"1\">"
|
||||
+ qsTr("<a href=\"#error\">Error</a>")
|
||||
+ "</strong></font>"
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
linkColor: theme.textErrorColor
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Describes an error that occurred when downloading")
|
||||
onLinkActivated: {
|
||||
downloadingErrorPopup.text = downloadError;
|
||||
downloadingErrorPopup.open();
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
visible: LLM.systemTotalRAMInGB() < ramrequired
|
||||
Layout.topMargin: 20
|
||||
Layout.leftMargin: 20
|
||||
Layout.maximumWidth: 300
|
||||
textFormat: Text.StyledText
|
||||
text: qsTr("<strong><font size=\"2\">WARNING: Not recommended for your hardware.")
|
||||
+ qsTr(" Model requires more memory (") + ramrequired
|
||||
+ qsTr(" GB) than your system has available (")
|
||||
+ LLM.systemTotalRAMInGBString() + ").</strong></font>"
|
||||
color: theme.textErrorColor
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
wrapMode: Text.WordWrap
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Error for incompatible hardware")
|
||||
onLinkActivated: {
|
||||
downloadingErrorPopup.text = downloadError;
|
||||
downloadingErrorPopup.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: isDownloading && !calcHash
|
||||
Layout.topMargin: 20
|
||||
Layout.leftMargin: 20
|
||||
Layout.minimumWidth: 200
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
spacing: 20
|
||||
|
||||
ProgressBar {
|
||||
id: itemProgressBar
|
||||
Layout.fillWidth: true
|
||||
width: 200
|
||||
value: bytesReceived / bytesTotal
|
||||
background: Rectangle {
|
||||
implicitHeight: 45
|
||||
color: theme.progressBackground
|
||||
radius: 3
|
||||
}
|
||||
contentItem: Item {
|
||||
implicitHeight: 40
|
||||
|
||||
Rectangle {
|
||||
width: itemProgressBar.visualPosition * parent.width
|
||||
height: parent.height
|
||||
radius: 2
|
||||
color: theme.progressForeground
|
||||
}
|
||||
}
|
||||
Accessible.role: Accessible.ProgressBar
|
||||
Accessible.name: qsTr("Download progressBar")
|
||||
Accessible.description: qsTr("Shows the progress made in the download")
|
||||
}
|
||||
|
||||
Label {
|
||||
id: speedLabel
|
||||
color: theme.textColor
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: speed
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: qsTr("Download speed")
|
||||
Accessible.description: qsTr("Download speed in bytes/kilobytes/megabytes per second")
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
visible: calcHash
|
||||
Layout.topMargin: 20
|
||||
Layout.leftMargin: 20
|
||||
Layout.minimumWidth: 200
|
||||
Layout.maximumWidth: 200
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
clip: true
|
||||
|
||||
Label {
|
||||
id: calcHashLabel
|
||||
color: theme.textColor
|
||||
text: qsTr("Calculating...")
|
||||
font.pixelSize: theme.fontSizeLarge
|
||||
Accessible.role: Accessible.Paragraph
|
||||
Accessible.name: text
|
||||
Accessible.description: qsTr("Whether the file hash is being calculated")
|
||||
}
|
||||
|
||||
MyBusyIndicator {
|
||||
id: busyCalcHash
|
||||
running: calcHash
|
||||
Accessible.role: Accessible.Animation
|
||||
Accessible.name: qsTr("Busy indicator")
|
||||
Accessible.description: qsTr("Displayed when the file hash is being calculated")
|
||||
}
|
||||
}
|
||||
|
||||
MyTextField {
|
||||
id: apiKey
|
||||
visible: !installed && isOnline
|
||||
Layout.topMargin: 20
|
||||
Layout.leftMargin: 20
|
||||
Layout.minimumWidth: 200
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
wrapMode: Text.WrapAnywhere
|
||||
function showError() {
|
||||
apiKey.placeholderTextColor = theme.textErrorColor
|
||||
}
|
||||
onTextChanged: {
|
||||
apiKey.placeholderTextColor = theme.mutedTextColor
|
||||
}
|
||||
placeholderText: qsTr("enter $API_KEY")
|
||||
Accessible.role: Accessible.EditableText
|
||||
Accessible.name: placeholderText
|
||||
Accessible.description: qsTr("Whether the file hash is being calculated")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
@ -206,7 +426,7 @@ Rectangle {
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: ramrequired + qsTr(" GB")
|
||||
text: ramrequired >= 0 ? ramrequired + qsTr(" GB") : "?"
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
@ -228,7 +448,7 @@ Rectangle {
|
||||
color: theme.mutedDarkTextColor
|
||||
}
|
||||
Text {
|
||||
text: parameters
|
||||
text: parameters !== "" ? parameters : "?"
|
||||
color: theme.textColor
|
||||
font.pixelSize: theme.fontSizeSmall
|
||||
font.bold: true
|
||||
@ -294,14 +514,6 @@ Rectangle {
|
||||
height: 1
|
||||
color: theme.dividerColor
|
||||
}
|
||||
|
||||
MySettingsButton {
|
||||
text: qsTr("Remove")
|
||||
textColor: theme.red500
|
||||
onClicked: Download.removeModel(filename)
|
||||
backgroundColor: "transparent"
|
||||
backgroundColorHovered: theme.lighterButtonBackgroundHoveredRed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user