Browse Source

custom file dialog to work around qt 5.5 bug

cl-refactor
arkpar 10 years ago
parent
commit
7d550846ed
  1. 5
      mix/CMakeLists.txt
  2. 8
      mix/FileIo.cpp
  3. 5
      mix/FileIo.h
  4. 3
      mix/MixApplication.cpp
  5. 2
      mix/MixClient.cpp
  6. 5
      mix/osx.qrc
  7. 1
      mix/qml.qrc
  8. 6
      mix/qml/Application.qml
  9. 298
      mix/qml/MacFileDialog.qml
  10. 2
      mix/qml/NewProjectDialog.qml
  11. 3
      mix/qml/PackagingStep.qml
  12. 5
      mix/qml/QFileDialog.qml
  13. 2
      mix/qml/StateDialog.qml

5
mix/CMakeLists.txt

@ -20,6 +20,11 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") AND NOT (CMAKE_CXX_COMPILER_VER
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override")
endif ()
#TODO: remove once qt 5.5.1 is out
if (APPLE)
qt5_add_resources(UI_RESOURCES osx.qrc)
endif()
find_package (Qt5WebEngine)
if (APPLE)
# TODO: remove indirect dependencies once macdeployqt is fixed

8
mix/FileIo.cpp

@ -224,3 +224,11 @@ void FileIo::deleteFile(QString const& _path)
QFile file(pathFromUrl(_path));
file.remove();
}
QUrl FileIo::pathFolder(QString const& _path)
{
QFileInfo info(_path);
if (info.exists() && info.isDir())
return QUrl::fromLocalFile(_path);
return QUrl::fromLocalFile(QFileInfo(_path).absolutePath());
}

5
mix/FileIo.h

@ -71,6 +71,11 @@ public:
/// delete a directory
Q_INVOKABLE void deleteDir(QString const& _url);
//TODO: remove once qt 5.5.1 is out
Q_INVOKABLE QString urlToPath(QUrl const& _url) { return _url.toLocalFile(); }
Q_INVOKABLE QUrl pathToUrl(QString const& _path) { return QUrl::fromLocalFile(_path); }
Q_INVOKABLE QUrl pathFolder(QString const& _path);
private:
QString getHomePath() const;
QString pathFromUrl(QString const& _url);

3
mix/MixApplication.cpp

@ -41,6 +41,9 @@
extern int qInitResources_js();
using namespace dev::mix;
ApplicationService::ApplicationService()
{
#ifdef ETH_HAVE_WEBENGINE

2
mix/MixClient.cpp

@ -284,7 +284,7 @@ void MixClient::mine()
RLPStream header;
h.streamRLP(header);
m_postMine.sealBlock(header.out());
bc().import(m_postMine.blockData(), m_stateDB, ImportRequirements::Everything & ~ImportRequirements::ValidSeal);
bc().import(m_postMine.blockData(), m_stateDB, (ImportRequirements::Everything & ~ImportRequirements::ValidSeal) != 0);
m_postMine.sync(bc());
m_preMine = m_postMine;
}

5
mix/osx.qrc

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file alias="qml/QFileDialog.qml">qml/MacFileDialog.qml</file>
</qresource>
</RCC>

1
mix/qml.qrc

@ -34,6 +34,7 @@
<file>qml/QStringTypeView.qml</file>
<file>qml/QVariableDeclaration.qml</file>
<file>qml/QVariableDefinition.qml</file>
<file>qml/QFileDialog.qml</file>
<file>qml/SourceSansProBold.qml</file>
<file>qml/SourceSansProLight.qml</file>
<file>qml/SourceSansProRegular.qml</file>

6
mix/qml/Application.qml

@ -281,11 +281,12 @@ ApplicationWindow {
onTriggered: openProjectFileDialog.open()
}
FileDialog {
QFileDialog {
id: openProjectFileDialog
visible: false
title: qsTr("Open a Project")
selectFolder: true
selectExisting: true
onAccepted: {
var path = openProjectFileDialog.fileUrl.toString();
path += "/";
@ -333,11 +334,12 @@ ApplicationWindow {
onTriggered: addExistingFileDialog.open()
}
FileDialog {
QFileDialog {
id: addExistingFileDialog
visible: false
title: qsTr("Add a File")
selectFolder: false
selectExisting: true
onAccepted: {
var paths = addExistingFileDialog.fileUrls;
projectModel.addExistingFiles(paths);

298
mix/qml/MacFileDialog.qml

@ -0,0 +1,298 @@
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Private 1.0 as ControlsPrivate
import QtQuick.Dialogs 1.2
import QtQuick.Dialogs.Private 1.1
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1
import Qt.labs.folderlistmodel 2.1
import Qt.labs.settings 1.0
AbstractDialog {
id: root
property string folder: view.model.folder
property var nameFilters: []
property bool selectFolder: false
property bool selectExisting: true
property int selectedNameFilterIndex: -1
property var selectedNameFilterExtensions: []
property string selection: ""
property alias fileUrl: root.selection
function selectNameFilter(text) {
}
function clearSelection(text) {
selection = "";
}
function addSelection(text) {
selection = text;
}
onVisibleChanged: {
if (visible) {
view.needsWidthAdjustment = true
view.selection.clear()
view.focus = true
}
}
Component.onCompleted: {
folder = fileIo.pathToUrl(fileIo.homePath);
view.model.nameFilters = root.selectedNameFilterExtensions
filterField.currentIndex = root.selectedNameFilterIndex
root.favoriteFolders = settings.favoriteFolders
}
Component.onDestruction: {
settings.favoriteFolders = root.favoriteFolders
}
property Settings settings: Settings {
category: "QQControlsFileDialog"
property alias width: root.width
property alias height: root.height
property variant favoriteFolders: []
}
property bool showFocusHighlight: false
property SystemPalette palette: SystemPalette { }
property var favoriteFolders: []
function dirDown(path) {
view.selection.clear()
root.folder = "file://" + path
}
function dirUp() {
view.selection.clear()
if (view.model.parentFolder != "")
root.folder = view.model.parentFolder
}
function acceptSelection() {
// transfer the view's selections to QQuickFileDialog
clearSelection()
if (selectFolder && view.selection.count === 0)
addSelection(folder)
else {
view.selection.forEach(function(idx) {
if (view.model.isFolder(idx)) {
if (selectFolder)
addSelection(view.model.get(idx, "fileURL"))
} else {
if (!selectFolder)
addSelection(view.model.get(idx, "fileURL"))
}
})
}
accept()
}
property Action dirUpAction: Action {
text: "\ue810"
shortcut: "Ctrl+U"
onTriggered: dirUp()
tooltip: qsTr("Go up to the folder containing this one")
}
Rectangle {
id: window
implicitWidth: Math.min(root.__maximumDimension, Math.max(Screen.pixelDensity * 100, view.implicitWidth))
implicitHeight: Math.min(root.__maximumDimension, Screen.pixelDensity * 80)
color: root.palette.window
Binding {
target: view.model
property: "folder"
value: root.folder
}
Binding {
target: currentPathField
property: "text"
value: fileIo.urlToPath(root.folder)
}
Keys.onPressed: {
event.accepted = true
switch (event.key) {
case Qt.Key_Back:
case Qt.Key_Escape:
reject()
break
default:
event.accepted = false
break
}
}
Keys.forwardTo: [view.flickableItem]
TableView {
id: view
sortIndicatorVisible: true
width: parent.width
anchors.top: titleBar.bottom
anchors.bottom: bottomBar.top
property bool needsWidthAdjustment: true
selectionMode: root.selectMultiple ?
(ControlsPrivate.Settings.hasTouchScreen ? SelectionMode.MultiSelection : SelectionMode.ExtendedSelection) :
SelectionMode.SingleSelection
onRowCountChanged: if (needsWidthAdjustment && rowCount > 0) {
resizeColumnsToContents()
needsWidthAdjustment = false
}
model: FolderListModel {
showFiles: !root.selectFolder
nameFilters: root.selectedNameFilterExtensions
sortField: (view.sortIndicatorColumn === 0 ? FolderListModel.Name :
(view.sortIndicatorColumn === 1 ? FolderListModel.Type :
(view.sortIndicatorColumn === 2 ? FolderListModel.Size : FolderListModel.LastModified)))
sortReversed: view.sortIndicatorOrder === Qt.DescendingOrder
}
onActivated: if (view.focus) {
if (view.selection.count > 0 && view.model.isFolder(row)) {
dirDown(view.model.get(row, "filePath"))
} else {
root.acceptSelection()
}
}
onClicked: currentPathField.text = view.model.get(row, "filePath")
TableViewColumn {
id: fileNameColumn
role: "fileName"
title: qsTr("Filename")
delegate: Item {
implicitWidth: pathText.implicitWidth + pathText.anchors.leftMargin + pathText.anchors.rightMargin
Text {
id: fileIcon
width: height
verticalAlignment: Text.AlignVCenter
font.family: iconFont.name
property alias unicode: fileIcon.text
FontLoader { id: iconFont; source: "qrc:/QtQuick/Dialogs/qml/icons.ttf"; onNameChanged: console.log("custom font" + name) }
x: 4
height: parent.height - 2
unicode: view.model.isFolder(styleData.row) ? "\ue804" : "\ue802"
}
Text {
id: pathText
text: styleData.value
anchors {
left: parent.left
right: parent.right
leftMargin: 36 + 6
rightMargin: 4
verticalCenter: parent.verticalCenter
}
color: styleData.textColor
elide: Text.ElideRight
renderType: ControlsPrivate.Settings.isMobile ? Text.QtRendering : Text.NativeRendering
}
}
}
TableViewColumn {
role: "fileSuffix"
title: qsTr("Type", "file type (extension)")
// TODO should not need to create a whole new component just to customize the text value
// something like textFormat: function(text) { return view.model.get(styleData.row, "fileIsDir") ? "folder" : text }
delegate: Item {
implicitWidth: sizeText.implicitWidth + sizeText.anchors.leftMargin + sizeText.anchors.rightMargin
Text {
id: sizeText
text: view.model.get(styleData.row, "fileIsDir") ? "folder" : styleData.value
anchors {
left: parent.left
right: parent.right
leftMargin: 4
rightMargin: 4
verticalCenter: parent.verticalCenter
}
color: styleData.textColor
elide: Text.ElideRight
renderType: ControlsPrivate.Settings.isMobile ? Text.QtRendering : Text.NativeRendering
}
}
}
TableViewColumn {
role: "fileSize"
title: qsTr("Size", "file size")
horizontalAlignment: Text.AlignRight
}
TableViewColumn { id: modifiedColumn; role: "fileModified" ; title: qsTr("Modified", "last-modified time") }
TableViewColumn { id: accessedColumn; role: "fileAccessed" ; title: qsTr("Accessed", "last-accessed time") }
}
ToolBar {
id: titleBar
RowLayout {
anchors.fill: parent
ToolButton {
action: dirUpAction
//style: IconButtonStyle { }
Layout.maximumWidth: height * 1.5
}
TextField {
id: currentPathField
Layout.fillWidth: true
function doAccept() {
root.clearSelection()
if (root.addSelection(fileIo.pathToUrl(text)))
root.accept()
else
root.folder = fileIo.pathFolder(text)
}
onAccepted: doAccept()
}
}
}
Item {
id: bottomBar
width: parent.width
height: buttonRow.height + buttonRow.spacing * 2
anchors.bottom: parent.bottom
Row {
id: buttonRow
anchors.right: parent.right
anchors.rightMargin: spacing
anchors.verticalCenter: parent.verticalCenter
spacing: 4
ComboBox {
id: filterField
model: root.nameFilters
visible: !selectFolder
width: bottomBar.width - cancelButton.width - okButton.width - parent.spacing * 6
anchors.verticalCenter: parent.verticalCenter
onCurrentTextChanged: {
root.selectNameFilter(currentText)
view.model.nameFilters = root.selectedNameFilterExtensions
}
}
Button {
id: cancelButton
text: qsTr("Cancel")
onClicked: root.reject()
}
Button {
id: okButton
text: root.selectFolder ? qsTr("Choose") : (selectExisting ? qsTr("Open") : qsTr("Save"))
onClicked: {
if (view.model.isFolder(view.currentIndex) && !selectFolder)
dirDown(view.model.get(view.currentIndex, "filePath"))
else if (!(root.selectExisting))
currentPathField.doAccept()
else
root.acceptSelection()
}
}
}
}
}
}

2
mix/qml/NewProjectDialog.qml

@ -105,7 +105,7 @@ Item
}
FileDialog {
QFileDialog {
id: createProjectFileDialog
visible: false
title: qsTr("Please choose a path for the project")

3
mix/qml/PackagingStep.qml

@ -27,11 +27,12 @@ Rectangle {
visible = true
}
FileDialog {
QFileDialog {
id: ressourcesFolder
visible: false
title: qsTr("Please choose a path")
selectFolder: true
selectExisting: true
property variant target
onAccepted: {
var u = ressourcesFolder.fileUrl.toString();

5
mix/qml/QFileDialog.qml

@ -0,0 +1,5 @@
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
FileDialog { }

2
mix/qml/StateDialog.qml

@ -124,7 +124,7 @@ Dialog {
importJsonFileDialog.open()
}
}
FileDialog {
QFileDialog {
id: importJsonFileDialog
visible: false
title: qsTr("Select State File")

Loading…
Cancel
Save