This commit is contained in:
Milan Nikolic
2015-12-02 20:46:42 +01:00
parent c8d472e576
commit b930b06a7d
11 changed files with 1922 additions and 156 deletions

BIN
gui/assets/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
gui/assets/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

965
gui/assets/main.qml Normal file
View File

@@ -0,0 +1,965 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
import Qt.labs.settings 1.0
ApplicationWindow {
id: applicationWindow
visible: true
width: 800
height: 600
title: "CBconvert"
property int margin: 15
property int screenWidth: Screen.width
property int screenHeight: Screen.height
function updateImage() {
imagePreview.source = ""
sizePreview.text = ""
if(groupBoxPreview.checked) {
if(c.len > 0) {
imagePreview.source = "image://cover/" + c.get(listView.currentIndex).path
}
}
}
ColumnLayout {
id: splitView1
anchors.rightMargin: margin
anchors.leftMargin: margin
anchors.bottomMargin: margin
anchors.topMargin: margin
anchors.fill: parent
RowLayout {
id: rowLayout1
anchors.bottom: rowLayout2.top
anchors.right: parent.right
anchors.left: parent.left
anchors.top: parent.top
anchors.bottomMargin: 15
Layout.minimumHeight: 250
ScrollView {
id: scrollview
anchors.right: columnButtons.left
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.top: parent.top
anchors.rightMargin: margin
frameVisible: true
highlightOnFocus: false
verticalScrollBarPolicy: 2
flickableItem.interactive: true
focus: true
ListView {
id: listView
anchors.topMargin: 0
anchors.fill: parent
spacing: 1
focus: true
model: c.len
header: Rectangle {
height: 20
width: ListView.view.width
color: "#DCDCDC"
Text {
id: nameHeader
text: 'Name'
anchors.left: parent.left
anchors.leftMargin: 5
anchors.verticalCenter: parent.verticalCenter
MouseArea {
anchors.fill: parent
onClicked: {
c.byName()
}
}
}
Text {
id: typeHeader
text: 'Type'
width: 40
anchors.right: sizeHeader.left
anchors.rightMargin: 40
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignHCenter
MouseArea {
anchors.fill: parent
onClicked: {
c.byType()
}
}
}
Text {
id: sizeHeader
text: 'Size'
width: 40
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignHCenter
MouseArea {
anchors.fill: parent
onClicked: {
c.bySize()
}
}
}
}
delegate: Item {
id: item1
width: ListView.view.width
height: 20
Text {
id: nameItem
text: c.get(index).name
anchors.left: parent.left
anchors.leftMargin: 5
anchors.verticalCenter: parent.verticalCenter
width: parent.width - 170
elide: Text.ElideRight
}
Text {
id: typeItem
width: 40
text: c.get(index).type
anchors.right: sizeItem.left
anchors.rightMargin: 40
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignHCenter
}
Text {
id: sizeItem
width: 40
text: c.get(index).sizeHuman
anchors.right: parent.right
anchors.rightMargin: 15
anchors.verticalCenter: parent.verticalCenter
horizontalAlignment: Text.AlignHCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
listView.currentIndex = index
listView.forceActiveFocus()
}
}
}
highlight: Rectangle {
width: ListView.view ? ListView.view.width : undefined
color: "#326686"
opacity: 0.2
y: listView.currentItem.y
Behavior on y {
SpringAnimation {
spring: 3
damping: 0.2
}
}
}
onCurrentItemChanged: updateImage()
}
}
ColumnLayout {
id: columnButtons
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.top: parent.top
anchors.topMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
ColumnLayout {
id: columnButtonsFiles
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
anchors.top: parent.top
anchors.topMargin: 0
spacing: 5
Button {
id: buttonAddFile
objectName: "buttonAddFile"
text: "Add &Files"
onClicked: {
fileDialogFile.open()
}
}
Button {
id: buttonAddDir
objectName: "buttonAddDir"
text: "Add &Dir"
onClicked: {
fileDialogDir.open()
}
}
Button {
id: buttonRemove
objectName: "buttonRemove"
text: "Remove"
enabled: (c.len !== 0) ? true : false
onClicked: {
c.remove(listView.currentIndex)
updateImage()
}
}
Button {
id: buttonRemoveAll
objectName: "buttonRemoveAll"
text: "Remove All"
enabled: (c.len !== 0) ? true : false
onClicked: {
c.removeAll()
updateImage()
}
}
}
ColumnLayout {
id: columnButtonsActions
anchors.left: parent.left
anchors.leftMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
spacing: 5
Button {
id: buttonThumbnail
objectName: "buttonThumbnail"
text: "Thumbnail"
anchors.bottom: buttonCover.top
anchors.bottomMargin: 5
tooltip: "Extract Thumbnail (freedesktop spec.)"
enabled: (textFieldOutDir.text != "" && c.len !== 0) ? true : false
}
Button {
id: buttonCover
objectName: "buttonCover"
text: "Cover"
anchors.bottom: buttonConvert.top
anchors.bottomMargin: 15
tooltip: "Extract Cover"
enabled: (textFieldOutDir.text != "" && c.len !== 0) ? true : false
}
Button {
id: buttonConvert
objectName: "buttonConvert"
text: "&Convert"
tooltip: "Convert archives and documents"
enabled: (textFieldOutDir.text != "" && c.len !== 0) ? true : false
}
}
}
}
RowLayout {
id: rowLayout2
spacing: 0
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.left: parent.left
ColumnLayout {
id: columnLeft
anchors.right: columnMiddle.left
anchors.rightMargin: margin
anchors.left: parent.left
anchors.leftMargin: 0
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.top: parent.top
anchors.topMargin: 0
Layout.minimumWidth: 200
GroupBox {
id: groupBoxPreview
checkable: true
flat: true
anchors.fill: parent
title: "Preview"
Image {
id: imagePreview
anchors.fill: parent
fillMode: Image.PreserveAspectFit
asynchronous: true
cache: false
}
BusyIndicator {
running: imagePreview.status === Image.Loading
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
onCheckedChanged: updateImage()
}
Text {
id: sizePreview
objectName: "sizePreview"
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: groupBoxPreview.bottom
anchors.topMargin: -5
}
}
ColumnLayout {
id: columnMiddle
anchors.right: columnRight.left
anchors.rightMargin: margin
anchors.top: parent.top
anchors.topMargin: 0
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
Layout.fillHeight: true
GroupBox {
id: groupBoxInput
flat: true
anchors.right: parent.right
anchors.rightMargin: 0
title: "Input"
anchors.top: parent.top
anchors.topMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
ColumnLayout {
id: columnInput
anchors.bottomMargin: 0
anchors.fill: parent
spacing: 5
CheckBox {
id: checkBoxRecursive
objectName: "checkBoxRecursive"
text: "Recurse SubDirectories"
}
CheckBox {
id: checkBoxNoRGB
objectName: "checkBoxNoRGB"
text: "Only Grayscaled Images"
}
CheckBox {
id: checkBoxConvertCover
objectName: "checkBoxConvertCover"
text: "Exclude Cover"
}
RowLayout {
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
spacing: 5
SpinBox {
id: spinboxSize
objectName: "spinboxSize"
stepSize: 10
prefix: ""
maximumValue: 1000
suffix: " MiB"
}
Text {
text: "Minimum Size"
}
}
}
}
GroupBox {
id: groupBoxTransform
flat: true
anchors.right: parent.right
anchors.rightMargin: 0
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
title: "Transform"
ColumnLayout {
id: columnTransform
anchors.fill: parent
spacing: 5
Button {
id: buttonLevels
text: "Levels..."
enabled: (c.len > 0) ? true : false
onClicked: {
levelsDialog.open()
}
}
Text {
text: "Brightness: " + sliderBrightness.value
}
Slider {
id: sliderBrightness
objectName: "sliderBrightness"
value: 0
stepSize: 1
minimumValue: -100
maximumValue: 100
activeFocusOnPress: true
updateValueWhileDragging: false
enabled: (c.len > 0) ? true : false
onValueChanged: updateImage()
}
Text {
text: "Contrast: " + sliderContrast.value
}
Slider {
id: sliderContrast
objectName: "sliderContrast"
value: 0
maximumValue: 100
stepSize: 1
minimumValue: -100
activeFocusOnPress: true
updateValueWhileDragging: false
enabled: (c.len > 0) ? true : false
onValueChanged: updateImage()
}
Text {
text: "Flip:"
}
ComboBox {
id: comboBoxFlip
objectName: "comboBoxFlip"
enabled: (c.len > 0) ? true : false
model: ListModel {
ListElement {
text: "None"
}
ListElement {
text: "Horizontal"
}
ListElement {
text: "Vertical"
}
}
onActivated: updateImage()
}
Text {
text: "Rotate:"
}
ComboBox {
id: comboBoxRotate
objectName: "comboBoxRotate"
enabled: (c.len > 0) ? true : false
model: ListModel {
ListElement {
text: "0"
}
ListElement {
text: "90"
}
ListElement {
text: "180"
}
ListElement {
text: "270"
}
}
onActivated: updateImage()
}
}
}
}
ColumnLayout {
id: columnRight
anchors.top: parent.top
anchors.topMargin: 0
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
Layout.fillHeight: true
GroupBox {
id: groupBoxOutput
flat: true
title: "Output"
anchors.top: parent.top
anchors.topMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
ColumnLayout {
id: columnOutput
anchors.bottomMargin: 0
anchors.fill: parent
spacing: 5
RowLayout {
id: rowLayoutOutput
anchors.top: parent.top
anchors.topMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
spacing: 5
TextField {
id: textFieldOutDir
objectName: "textFieldOutDir"
anchors.right: buttonBrowse.left
anchors.rightMargin: 5
anchors.left: parent.left
anchors.leftMargin: 0
placeholderText: "Output Directory"
Settings {
id: settingsOutDir
property alias text: textFieldOutDir.text
}
}
Button {
id: buttonBrowse
text: "..."
anchors.right: parent.right
anchors.rightMargin: 0
anchors.verticalCenter: parent.verticalCenter
onClicked: {
fileDialogOutput.open()
}
}
}
TextField {
id: textFieldSuffix
objectName: "textFieldSuffix"
anchors.left: parent.left
anchors.leftMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
placeholderText: "Add Suffix to Output File"
}
CheckBox {
id: checkBoxNonImage
objectName: "checkBoxNonImage"
text: "Remove Non-Image Files"
}
}
}
GroupBox {
id: groupBoxImage
flat: true
anchors.left: parent.left
anchors.leftMargin: 0
title: "Image"
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
ColumnLayout {
id: columnFormat
anchors.fill: parent
spacing: 5
Text {
text: "Format:"
}
ComboBox {
id: comboBoxFormat
objectName: "comboBoxFormat"
enabled: (c.len > 0) ? true : false
model: ListModel {
ListElement {
text: "JPEG"
}
ListElement {
text: "PNG"
}
ListElement {
text: "GIF"
}
ListElement {
text: "BMP"
}
ListElement {
text: "TIFF"
}
}
onActivated: updateImage()
}
Text {
text: "Size:"
}
RowLayout {
spacing: 5
TextField {
id: width
objectName: "width"
placeholderText: "width"
maximumLength: 4
implicitWidth: 50
onAccepted: updateImage()
}
Text {
id: x
text: "x"
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
}
TextField {
id: height
objectName: "height"
placeholderText: "height"
maximumLength: 4
implicitWidth: 50
onAccepted: updateImage()
}
}
CheckBox {
id: checkBoxFit
objectName: "checkBoxFit"
text: "Best Fit"
enabled: (c.len > 0) ? true : false
onClicked: updateImage()
}
Text {
text: "Resize Algorithm:"
}
ComboBox {
id: comboBoxFilter
objectName: "comboBoxFilter"
currentIndex: 2
enabled: (c.len > 0) ? true : false
model: ListModel {
ListElement {
text: "NearestNeighbor"
}
ListElement {
text: "Box"
}
ListElement {
text: "Linear"
}
ListElement {
text: "MitchellNetravali"
}
ListElement {
text: "CatmullRom"
}
ListElement {
text: "Gaussian"
}
ListElement {
text: "Lanczos"
}
}
onActivated: updateImage()
Settings {
id: settingsFilter
property alias currentIndex: comboBoxFilter.currentIndex
}
}
Text {
text: "Quality: " + sliderQuality.value
}
Slider {
id: sliderQuality
objectName: "sliderQuality"
stepSize: 1
value: 75
maximumValue: 100
activeFocusOnPress: true
updateValueWhileDragging: false
enabled: (c.len > 0 && comboBoxFormat.currentText == "JPEG") ? true : false
onValueChanged: updateImage()
}
CheckBox {
id: checkBoxGrayscale
objectName: "checkBoxGrayscale"
text: "Convert to Grayscale"
enabled: (c.len > 0) ? true : false
onClicked: updateImage()
}
Settings {
id: settingsQuality
property alias value: sliderQuality.value
}
}
}
}
}
}
FileDialog {
id: fileDialogFile
modality: Qt.WindowModal
title: "Add Files"
selectFolder: false
selectMultiple: true
selectExisting: true
sidebarVisible: true
nameFilters: [ "Comic files (*.rar *.zip *.7z *.gz *.bz2 *.cbr *.cbz *.cb7 *.cbt *.pdf *.epub *.xps)" ]
onAccepted: {
c.addUrls(decodeURIComponent(fileUrls.join("_CBSEP_")))
}
}
FileDialog {
id: fileDialogDir
modality: Qt.WindowModal
title: "Add Directory"
selectFolder: true
sidebarVisible: true
onAccepted: {
c.addUrls(decodeURIComponent(fileUrl.toString()))
}
}
FileDialog {
id: fileDialogOutput
modality: Qt.WindowModal
title: "Output Directory"
selectFolder: true
sidebarVisible: true
onAccepted: {
textFieldOutDir.text = decodeURIComponent(fileUrl.toString().replace("file://", ""))
}
}
Dialog {
id: levelsDialog
objectName: "levelsDialog"
title: "Levels"
standardButtons: StandardButton.Close
width: 230
height: 150
ColumnLayout {
anchors.fill: parent
Text {
text: "Input Levels:"
}
RowLayout {
anchors.left: parent.left
anchors.leftMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
spacing: 5
SpinBox {
id: spinboxLevelsInMin
objectName: "spinboxLevelsInMin"
anchors.left: parent.left
anchors.leftMargin: 0
stepSize: 1
maximumValue: 255
value: 0
onEditingFinished: updateImage()
Keys.onReturnPressed: {
event.accepted = true
}
}
SpinBox {
id: spinboxLevelsGamma
objectName: "spinboxLevelsGamma"
anchors.horizontalCenter: parent.horizontalCenter
decimals: 2
stepSize: 0.01
maximumValue: 10.00
value: 1.00
onEditingFinished: updateImage()
}
SpinBox {
id: spinboxLevelsInMax
objectName: "spinboxLevelsInMax"
anchors.right: parent.right
anchors.rightMargin: 0
stepSize: 1
maximumValue: 255
value: 255
onEditingFinished: updateImage()
}
}
Text {
text: "Output Levels:"
}
RowLayout {
anchors.left: parent.left
anchors.leftMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
spacing: 5
SpinBox {
id: spinboxLevelsOutMin
objectName: "spinboxLevelsOutMin"
anchors.left: parent.left
anchors.leftMargin: 0
stepSize: 1
maximumValue: 255
value: 0
onEditingFinished: updateImage()
}
SpinBox {
id: spinboxLevelsOutMax
objectName: "spinboxLevelsOutMax"
anchors.right: parent.right
anchors.rightMargin: 0
stepSize: 1
maximumValue: 255
value: 255
onEditingFinished: updateImage()
}
}
}
}
statusBar: StatusBar {
RowLayout {
anchors.fill: parent
Label {
id: labelStatus
objectName: "labelStatus"
text: "Ready"
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
id: rectangle1
Layout.fillWidth: true
anchors.verticalCenter: parent.verticalCenter
Label {
id: labelPercent
objectName: "labelPercent"
font.pointSize: 9
anchors.right: progressBar.left
anchors.rightMargin: 5
anchors.verticalCenter: parent.verticalCenter
}
ProgressBar {
id: progressBar
objectName: "progressBar"
visible: false
value: 0.0
minimumValue : 0.0
maximumValue : 100.0
anchors.bottom: parent.bottom
anchors.bottomMargin: -10
anchors.top: parent.top
anchors.topMargin: -10
anchors.right: labelProgress.left
anchors.rightMargin: 5
}
Label {
id: labelProgress
objectName: "labelProgress"
font.pointSize: 9
anchors.right: parent.right
anchors.rightMargin: 0
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
}