" + "Sci-Hub EVA " +
qsTr("is a cross-platform Sci-Hub GUI Application.") + "
" +
"Powered By Python " + PYTHON_VERSION + " & Qt " + QT_VERSION + "
Copyright (c) 2018-2022 " + qsTr("Leo Van") +
+ " Copyright (c) 2018-2023 " + qsTr("Leo Van") +
" The MIT License
" +
- qsTr("{author}: Author, {year}: Year, {title}: Title, {id}: DOI or PMID")
- Layout.columnSpan: 2
- }
+ TextField {
+ id: textFieldPreferencesFileFilenamePrefixFormat
- Label {
- text: qsTr("Overwrite Existing File: ")
- }
+ Layout.fillWidth: true
+
+ selectByMouse: true
+ }
+ }
+
+ RowLayout {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ Label {
+ text: qsTr("Supported Keywords: ")
+
+ Layout.alignment: Qt.AlignTop
+ }
+
+ ColumnLayout {
+ Label {
+ text: qsTr("{author}: Author")
+ }
+
+ Label {
+ text: qsTr("{year}: Year")
+ }
+
+ Label {
+ text: qsTr("{title}: Title")
+ }
- Switch {
- id: switchPreferencesFileOverwrite
- text: checked ? qsTr("Yes") : qsTr("No")
- display: AbstractButton.TextBesideIcon
+ Label {
+ text: qsTr("{id}: DOI or PMID")
+ }
+ }
+ }
}
}
}
Item {
- id: itemTabPreferencesNetwork
+ id: itemPreferencesNetwork
- Layout.fillHeight: true
- Layout.fillWidth: true
+ ScrollView {
+ id: scrollViewPreferencesNetwork
- GridLayout {
- rowSpacing: 0
- columnSpacing: 3
-
- anchors.right: parent.right
- anchors.left: parent.left
- anchors.top: parent.top
+ anchors.fill: parent
- rows: 9
- columns: 2
+ ColumnLayout {
+ width: Math.max(implicitWidth, scrollViewPreferencesNetwork.width)
- Label {
- text: qsTr("SciHub URL: ")
- }
+ RowLayout {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
- RowLayout {
- Layout.fillWidth: true
+ Label {
+ text: qsTr("SciHub URL: ")
+ }
- ComboBox {
- id: comboBoxPreferencesNetworkSciHubURL
+ ComboBox {
+ id: comboBoxPreferencesNetworkSciHubURL
- Layout.minimumWidth: 160
- Layout.fillWidth: true
- }
+ Layout.fillWidth: true
+ }
- RoundButton {
- id: roundButtonPreferencesNetworkSciHubURLAdd
- text: "+"
+ RoundButton {
+ id: roundButtonPreferencesNetworkSciHubURLAdd
+ text: "+"
- onClicked: {
- showUIAddSciHubURL()
+ onClicked: {
+ showUIAddSciHubURL()
+ }
}
- }
- RoundButton {
- id: roundButtonPreferencesNetworkSciHubURLRemove
- text: "-"
-
- onClicked: {
- if (comboBoxPreferencesNetworkSciHubURL.count <= 1) {
- dialogPreferencesMessage.messageType = "error"
- dialogPreferencesMessage.message = qsTr("Cannot remove the last Sci-Hub URL!")
- dialogPreferencesMessage.open()
- } else {
- var message = qsTr("Delete Sci-Hub URL: ") + comboBoxPreferencesNetworkSciHubURL.currentText + " ?"
- dialogPreferencesRemoveSciHubURLConfirmMessage.messageType = "question"
- dialogPreferencesRemoveSciHubURLConfirmMessage.message = message
- dialogPreferencesRemoveSciHubURLConfirmMessage.open()
+ RoundButton {
+ id: roundButtonPreferencesNetworkSciHubURLRemove
+ text: "-"
+
+ onClicked: {
+ if (comboBoxPreferencesNetworkSciHubURL.count <= 1) {
+ dialogPreferencesMessage.messageType = "error"
+ dialogPreferencesMessage.message = qsTr("Cannot remove the last Sci-Hub URL!")
+ dialogPreferencesMessage.open()
+ } else {
+ var message = qsTr("Delete Sci-Hub URL: ") + comboBoxPreferencesNetworkSciHubURL.currentText + " ?"
+ dialogPreferencesRemoveSciHubURLConfirmMessage.messageType = "question"
+ dialogPreferencesRemoveSciHubURLConfirmMessage.message = message
+ dialogPreferencesRemoveSciHubURLConfirmMessage.open()
+ }
}
}
}
- }
- Label {
- text: qsTr("Timeout: ")
- }
+ RowLayout {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
- RowLayout {
- width: 100
- height: 100
- TextField {
- id: textFieldPreferencesNetworkTimeout
+ Label {
+ text: qsTr("Timeout: ")
+ }
- implicitWidth: 60
- Layout.fillWidth: false
+ TextField {
+ id: textFieldPreferencesNetworkTimeout
- horizontalAlignment: Text.AlignHCenter
- selectByMouse: true
- validator: RegularExpressionValidator {
- regularExpression: /[0-9]+/
+ Layout.fillWidth: true
+
+ horizontalAlignment: Text.AlignHCenter
+ selectByMouse: true
+ validator: RegularExpressionValidator {
+ regularExpression: /[0-9]+/
+ }
}
- }
- Label {
- text: "ms"
- }
- }
+ Label {
+ text: "ms"
+ }
- Label {
- text: qsTr("Retry Times: ")
- }
+ ToolSeparator {}
+
+ Label {
+ text: qsTr("Retry Times: ")
+ }
- TextField {
- id: textFieldPreferencesNetworkRetryTimes
+ TextField {
+ id: textFieldPreferencesNetworkRetryTimes
- implicitWidth: 60
- Layout.fillWidth: false
+ Layout.fillWidth: true
- horizontalAlignment: Text.AlignHCenter
- selectByMouse: true
- validator: RegularExpressionValidator {
- regularExpression: /[0-9]+/
+ horizontalAlignment: Text.AlignHCenter
+ selectByMouse: true
+ validator: RegularExpressionValidator {
+ regularExpression: /[0-9]+/
+ }
+ }
}
- }
- Label {
- text: qsTr("Enable Proxy")
- }
+ RowLayout {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
- Switch {
- id: switchPreferencesNetworkEnableProxy
- text: checked ? qsTr("Yes") : qsTr("No")
- }
+ Label {
+ text: qsTr("Enable Proxy")
+ }
- Label {
- text: qsTr("Proxy Type: ")
- }
+ Switch {
+ id: switchPreferencesNetworkEnableProxy
+ }
- RowLayout {
- width: 100
- height: 100
+ ToolSeparator {}
- RadioButton {
- id: radioButtonPreferencesNetworkProxyTypeHTTP
- text: "HTTP"
- }
+ Label {
+ text: qsTr("Proxy Type: ")
+ }
- RadioButton {
- id: radioButtonPreferencesNetworkProxyTypeSocks5
- text: "SOCKS5"
+ RadioButton {
+ id: radioButtonPreferencesNetworkProxyTypeHTTP
+ text: "HTTP"
+ }
+
+ RadioButton {
+ id: radioButtonPreferencesNetworkProxyTypeSocks5
+ text: "SOCKS5"
+ }
}
- }
+ RowLayout {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
- Label {
- text: qsTr("Proxy Host: ")
- }
+ Label {
+ text: qsTr("Proxy Host: ")
+ }
- TextField {
- id: textFieldPreferencesNetworkProxyHost
+ TextField {
+ id: textFieldPreferencesNetworkProxyHost
- implicitWidth: 200
- Layout.fillWidth: true
+ Layout.fillWidth: true
- selectByMouse: true
- }
+ selectByMouse: true
+ }
+ }
- Label {
- text: qsTr("Proxy Port: ")
- }
+ RowLayout {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ Label {
+ text: qsTr("Proxy Port: ")
+ }
- TextField {
- id: textFieldPreferencesNetworkProxyPort
+ TextField {
+ id: textFieldPreferencesNetworkProxyPort
- implicitWidth: 200
- Layout.fillWidth: true
+ Layout.fillWidth: true
- selectByMouse: true
- validator: RegularExpressionValidator {
- regularExpression: /[0-9]+/
+ selectByMouse: true
+ validator: RegularExpressionValidator {
+ regularExpression: /[0-9]+/
+ }
+ }
}
- }
- Label {
- text: qsTr("Proxy Username: ")
- }
+ RowLayout {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
- TextField {
- id: textFieldPreferencesNetworkProxyUsername
+ Label {
+ text: qsTr("Proxy Username: ")
+ }
- implicitWidth: 200
- Layout.fillWidth: true
+ TextField {
+ id: textFieldPreferencesNetworkProxyUsername
- selectByMouse: true
- }
+ Layout.fillWidth: true
- Label {
- text: qsTr("Proxy Password: ")
- }
+ selectByMouse: true
+ }
+ }
+
+ RowLayout {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ Label {
+ text: qsTr("Proxy Password: ")
+ }
- TextField {
- id: textFieldPreferencesNetworkProxyPassword
+ TextField {
+ id: textFieldPreferencesNetworkProxyPassword
- implicitWidth: 200
- Layout.fillWidth: true
+ Layout.fillWidth: true
- echoMode: TextInput.Password
+ echoMode: TextInput.Password
+ }
+ }
}
}
}
@@ -640,5 +670,3 @@ ApplicationWindow {
}
}
}
-
-
diff --git a/ui/SciHubEVA.qml b/ui/SciHubEVA.qml
index 73b40b7..e9e0074 100644
--- a/ui/SciHubEVA.qml
+++ b/ui/SciHubEVA.qml
@@ -16,7 +16,7 @@ ApplicationWindow {
visible: true
- property int margin: 10
+ property int margin: 8
property int theme: Material.theme
width: columnLayoutApplication.implicitWidth + 2 * margin
@@ -165,6 +165,7 @@ ApplicationWindow {
text: qsTr("Rampage")
font.bold: false
+ Layout.minimumWidth: implicitWidth
Layout.fillWidth: true
onClicked: {
@@ -187,6 +188,7 @@ ApplicationWindow {
text: qsTr("Load")
font.bold: false
+ Layout.minimumWidth: implicitWidth
Layout.fillWidth: true
onClicked: fileDialogQueryList.open()
@@ -221,6 +223,7 @@ ApplicationWindow {
text: qsTr("Open")
font.bold: false
+ Layout.minimumWidth: implicitWidth
Layout.fillWidth: true
onClicked: folderDialogSaveTo.open()
@@ -231,6 +234,7 @@ ApplicationWindow {
text: qsTr("Show")
font.bold: false
+ Layout.minimumWidth: implicitWidth
Layout.fillWidth: true
onClicked: systemOpenSaveToDir(textFieldSaveToDir.text.trim())
@@ -256,26 +260,28 @@ ApplicationWindow {
flickableDirection: Flickable.VerticalFlick
- Layout.minimumWidth: 600
Layout.minimumHeight: 200
+ Layout.fillWidth: true
- function scrollToBottom() {
- if (contentHeight > height) {
- contentY = contentHeight - height
- }
+ ScrollBar.vertical: UIElements.ScrollBar {
+ id: scrollBarLogs
}
TextArea.flickable: TextArea {
id: textAreaLogs
- font.pointSize: labelLogs.font.pointSize
textFormat: Text.RichText
wrapMode: Text.WordWrap
readOnly: true
selectByMouse: true
horizontalAlignment: Text.AlignLeft
- onTextChanged: flickableLogs.scrollToBottom()
+ Layout.fillWidth: true
+
+ onTextChanged: {
+ scrollBarLogs.position = 1.0 - scrollBarLogs.size
+ }
+
onLinkActivated: (link) => {
Qt.openUrlExternally(link)
}
diff --git a/ui/elements/IconButton.qml b/ui/elements/IconButton.qml
index bf182d5..b17d6c2 100644
--- a/ui/elements/IconButton.qml
+++ b/ui/elements/IconButton.qml
@@ -6,14 +6,29 @@ Button {
id: button
property string iconSource
- property real iconSize: labelText.font.pointSize * 1.6
+ readonly property real iconSize: 20
+ readonly property bool hasIcon: iconSource.toString().length > 0
+ readonly property bool hasText: button.text.toString().length > 0
+ readonly property bool hasOnlyIcon: hasIcon && !hasText
- implicitWidth: leftPadding + rightPadding + rowContent.implicitWidth
+ topInset: 6
+ bottomInset: 6
+ verticalPadding: 14
+ leftPadding: hasOnlyIcon ? 8 : hasIcon ? 16 : 24
+ rightPadding: hasOnlyIcon ? 8 : 24
+
+ implicitWidth: hasIcon ?
+ Math.min(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding) :
+ Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
contentItem: Row {
id: rowContent
- spacing: 6
+ spacing: 8
anchors.horizontalCenter: parent.horizontalCenter
AnimatedImage {
@@ -21,13 +36,13 @@ Button {
playing: true
source: iconSource
height: iconSize
- width: iconSize
+ width: hasIcon ? iconSize : 0
anchors.verticalCenter: parent.verticalCenter
}
Label {
id: labelText
- text: parent.parent.text
+ text: button.text
anchors.verticalCenter: parent.verticalCenter
}
}
diff --git a/ui/elements/ItemDelegate.qml b/ui/elements/ItemDelegate.qml
new file mode 100644
index 0000000..354fa89
--- /dev/null
+++ b/ui/elements/ItemDelegate.qml
@@ -0,0 +1,60 @@
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import QtQuick.Controls.impl
+import QtQuick.Controls.Material
+import QtQuick.Controls.Material.impl
+import QtQml.Models
+
+ItemDelegate {
+ id: control
+
+ readonly property real iconSize: 20
+
+ highlighted: ListView.isCurrentItem
+
+ RowLayout {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ anchors.fill: parent
+ Layout.alignment: Qt.AlignCenter | Qt.AlignVCenter
+
+ Image {
+ source: iconSource
+
+ sourceSize.height: iconSize
+ sourceSize.width: iconSize
+
+ Layout.leftMargin: 8
+ }
+
+ Label {
+ id: labelDelegateToolsItemText
+
+ text: name
+ font.weight: Font.Medium
+
+ Layout.rightMargin: 8
+ Layout.fillWidth: true
+ }
+ }
+
+ background: Rectangle {
+ implicitHeight: control.Material.delegateHeight
+ color: control.highlighted ? control.Material.listHighlightColor : "transparent"
+ radius: Material.ExtraSmallScale
+
+ Ripple {
+ width: parent.width
+ height: parent.height
+
+ clip: visible
+ pressed: control.pressed
+ anchor: control
+ active: enabled && (control.down || control.visualFocus || control.hovered)
+ color: control.Material.rippleColor
+ clipRadius: Material.ExtraSmallScale
+ }
+ }
+}
diff --git a/ui/elements/Message.qml b/ui/elements/Message.qml
index 05abc0f..98fdfed 100644
--- a/ui/elements/Message.qml
+++ b/ui/elements/Message.qml
@@ -4,18 +4,25 @@ import QtQuick.Controls
import QtQuick.Window
Dialog {
+ id: dialog
+
x: (parent.width - width) / 2
y: (parent.height - height) / 2
modal: true
closePolicy: Popup.NoAutoClose
+ Material.roundedScale: Material.SmallScale
property string message
property string messageType
ColumnLayout {
anchors.fill: parent
+ focus: true
+
+ Keys.onReturnPressed: dialog.accept()
+ Keys.onEscapePressed: dialog.reject()
RowLayout {
Layout.fillWidth: true
diff --git a/ui/elements/ScrollBar.qml b/ui/elements/ScrollBar.qml
new file mode 100644
index 0000000..270501a
--- /dev/null
+++ b/ui/elements/ScrollBar.qml
@@ -0,0 +1,55 @@
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Material
+
+T.ScrollBar {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: control.interactive ? 1 : 2
+ visible: control.policy !== T.ScrollBar.AlwaysOff
+ minimumSize: orientation === Qt.Horizontal ? height / width : width / height
+
+ contentItem: Rectangle {
+ implicitWidth: control.interactive ? 9 : 4
+ implicitHeight: control.interactive ? 9 : 4
+
+ color: control.pressed ? control.Material.scrollBarPressedColor :
+ control.interactive && control.hovered ? control.Material.scrollBarHoveredColor : control.Material.scrollBarColor
+ opacity: 0.0
+ radius: Material.ExtraSmallScale
+ }
+
+ background: Rectangle {
+ implicitWidth: control.interactive ? 12 : 4
+ implicitHeight: control.interactive ? 12 : 4
+ color: "#0e000000"
+ opacity: 0.0
+ radius: Material.ExtraSmallScale
+ visible: control.interactive
+ }
+
+ states: State {
+ name: "active"
+ when: control.policy === T.ScrollBar.AlwaysOn || (control.active && control.size < 1.0)
+ }
+
+ transitions: [
+ Transition {
+ to: "active"
+ NumberAnimation { targets: [control.contentItem, control.background]; property: "opacity"; to: 1.0 }
+ },
+ Transition {
+ from: "active"
+ SequentialAnimation {
+ PropertyAction{ targets: [control.contentItem, control.background]; property: "opacity"; value: 1.0 }
+ PauseAnimation { duration: 2450 }
+ NumberAnimation { targets: [control.contentItem, control.background]; property: "opacity"; to: 0.0 }
+ }
+ }
+ ]
+}