[app] Implemented folder renaming
This commit is contained in:
parent
8a4e131452
commit
57204d3cc4
7 changed files with 129 additions and 61 deletions
|
@ -37,10 +37,27 @@ MouseArea {
|
||||||
implicitHeight: column.implicitHeight
|
implicitHeight: column.implicitHeight
|
||||||
property alias text: label.text
|
property alias text: label.text
|
||||||
property bool currentFolder
|
property bool currentFolder
|
||||||
|
property bool editable
|
||||||
|
property bool _editing
|
||||||
property bool _highlighted: pressed
|
property bool _highlighted: pressed
|
||||||
property color _highlightedColor: Theme.rgba(Theme.highlightBackgroundColor, Theme.highlightBackgroundOpacity)
|
property color _highlightedColor: Theme.rgba(Theme.highlightBackgroundColor, Theme.highlightBackgroundOpacity)
|
||||||
property bool _showPress: !currentFolder && (_highlighted || pressTimer.running)
|
property bool _showPress: !currentFolder && (_highlighted || pressTimer.running)
|
||||||
|
|
||||||
|
signal rename(var to)
|
||||||
|
|
||||||
|
function editName() {
|
||||||
|
if (editable && !_editing) {
|
||||||
|
editor.text = text
|
||||||
|
_editing = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onEditableChanged: {
|
||||||
|
if (!editable && _editing) {
|
||||||
|
_editing = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: column
|
id: column
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
@ -52,8 +69,7 @@ MouseArea {
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: labelItem
|
width: parent.width
|
||||||
width: Math.min(label.implicitWidth + icon.width + 3*Theme.paddingMedium, parent.width)
|
|
||||||
height: label.implicitHeight
|
height: label.implicitHeight
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
|
@ -72,66 +88,53 @@ MouseArea {
|
||||||
Label {
|
Label {
|
||||||
id: label
|
id: label
|
||||||
truncationMode: TruncationMode.Fade
|
truncationMode: TruncationMode.Fade
|
||||||
width: Math.min(parent.width - 2*Theme.paddingMedium, implicitWidth)
|
|
||||||
anchors {
|
anchors {
|
||||||
left: icon.right
|
left: icon.right
|
||||||
leftMargin: Theme.paddingMedium
|
leftMargin: Theme.paddingMedium
|
||||||
verticalCenter: parent.verticalCenter
|
verticalCenter: parent.verticalCenter
|
||||||
}
|
}
|
||||||
|
onTextChanged: {
|
||||||
|
if (!_editing) {
|
||||||
|
editor.text = text
|
||||||
|
}
|
||||||
|
}
|
||||||
color: (currentFolder || pressed) ? Theme.highlightColor : Theme.primaryColor
|
color: (currentFolder || pressed) ? Theme.highlightColor : Theme.primaryColor
|
||||||
|
opacity: _editing ? 0 : 1
|
||||||
|
visible: opacity > 0
|
||||||
Behavior on color { ColorAnimation { duration: 100 } }
|
Behavior on color { ColorAnimation { duration: 100 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: editor
|
||||||
|
width: parent.width - icon.width - 2*Theme.paddingMedium
|
||||||
|
y: 0
|
||||||
|
anchors {
|
||||||
|
left: icon.right
|
||||||
|
leftMargin: Theme.paddingMedium
|
||||||
|
}
|
||||||
|
textLeftMargin: 0
|
||||||
|
textRightMargin: 0
|
||||||
|
textTopMargin: 0
|
||||||
|
opacity: _editing ? 1 : 0
|
||||||
|
visible: opacity > 0
|
||||||
|
placeholderText: "Enter folder name"
|
||||||
|
onTextChanged: console.log(text)
|
||||||
|
EnterKey.onClicked: {
|
||||||
|
if (_editing) {
|
||||||
|
if (text) {
|
||||||
|
root.rename(text)
|
||||||
|
}
|
||||||
|
_editing = false
|
||||||
|
parent.focus = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
height: Theme.paddingSmall
|
height: Theme.paddingSmall
|
||||||
width: parent.width
|
width: parent.width
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Item {
|
|
||||||
width: labelItem.width
|
|
||||||
height: 3*Math.floor(PointsPerInch/100)
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: shelfLeft
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
leftMargin: Theme.paddingMedium
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
height: parent.height
|
|
||||||
sourceSize.height: height
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
source: "images/shelf-left.svg"
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: shelfRight
|
|
||||||
anchors {
|
|
||||||
right: parent.right
|
|
||||||
rightMargin: Theme.paddingMedium
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
height: parent.height
|
|
||||||
sourceSize.height: height
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
source: "images/shelf-right.svg"
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
anchors {
|
|
||||||
left: shelfLeft.right
|
|
||||||
right: shelfRight.left
|
|
||||||
bottom: parent.bottom
|
|
||||||
}
|
|
||||||
height: parent.height
|
|
||||||
sourceSize.height: height
|
|
||||||
sourceSize.width: width
|
|
||||||
source: "images/shelf-middle.svg"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressed: pressTimer.start()
|
onPressed: pressTimer.start()
|
||||||
|
|
|
@ -75,6 +75,7 @@ SilicaFlickable {
|
||||||
BooksPathModel {
|
BooksPathModel {
|
||||||
id: pathModel
|
id: pathModel
|
||||||
path: shelfModel.relativePath
|
path: shelfModel.relativePath
|
||||||
|
storage: shelfModel.storage
|
||||||
}
|
}
|
||||||
|
|
||||||
onEditModeChanged: {
|
onEditModeChanged: {
|
||||||
|
@ -175,17 +176,24 @@ SilicaFlickable {
|
||||||
BooksShelfTitle {
|
BooksShelfTitle {
|
||||||
width: grid.width
|
width: grid.width
|
||||||
text: model.name
|
text: model.name
|
||||||
|
editable: editMode
|
||||||
currentFolder: model.index === (pathModel.count-1)
|
currentFolder: model.index === (pathModel.count-1)
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (currentFolder) {
|
if (currentFolder) {
|
||||||
if (editMode) {
|
if (editMode) {
|
||||||
console.log("how about renaming", model.name)
|
console.log("editing", model.name)
|
||||||
|
editName()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("switching to", model.path)
|
console.log("switching to", model.path)
|
||||||
|
shelfView.stopEditing()
|
||||||
shelfModel.relativePath = model.path
|
shelfModel.relativePath = model.path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onRename: {
|
||||||
|
console.log(to)
|
||||||
|
model.name = to
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,8 +74,8 @@ SilicaFlickable {
|
||||||
|
|
||||||
function calculateCellWidth() {
|
function calculateCellWidth() {
|
||||||
// At least 3 books in portrait, 5 in landscape
|
// At least 3 books in portrait, 5 in landscape
|
||||||
var result2 = calculateCellWidth2(Math.min(width, height), 3)
|
var result2 = calculateCellWidth2(Math.min(window.width, window.height), 3)
|
||||||
var result1 = calculateCellWidth2(Math.max(width, height), 5)
|
var result1 = calculateCellWidth2(Math.max(window.width, window.height), 5)
|
||||||
var result = Math.min(result1, result2)
|
var result = Math.min(result1, result2)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
|
|
||||||
#include "HarbourDebug.h"
|
#include "HarbourDebug.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
enum BooksPathModelRole {
|
enum BooksPathModelRole {
|
||||||
BooksPathModelName = Qt::UserRole,
|
BooksPathModelName = Qt::UserRole,
|
||||||
BooksPathModelPath
|
BooksPathModelPath
|
||||||
|
@ -60,17 +62,20 @@ void BooksPathModel::setPath(QString aPath)
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
QString path;
|
QString path;
|
||||||
QStringList newPaths;
|
QStringList pathList;
|
||||||
|
QStringList parentList;
|
||||||
for (i=0; i<newSize; i++) {
|
for (i=0; i<newSize; i++) {
|
||||||
|
parentList.append(path);
|
||||||
if (!path.isEmpty()) path += "/";
|
if (!path.isEmpty()) path += "/";
|
||||||
path += newNames.at(i);
|
path += newNames.at(i);
|
||||||
newPaths.append(path);
|
pathList.append(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldSize < newSize) {
|
if (oldSize < newSize) {
|
||||||
beginInsertRows(QModelIndex(), oldSize, newSize-1);
|
beginInsertRows(QModelIndex(), oldSize, newSize-1);
|
||||||
for (int i=oldSize; i<newSize; i++) {
|
for (int i=oldSize; i<newSize; i++) {
|
||||||
iList.append(Data(newNames.at(i), newPaths.at(i)));
|
Data data(parentList.at(i), pathList.at(i), newNames.at(i));
|
||||||
|
iList.append(data);
|
||||||
}
|
}
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
Q_EMIT countChanged();
|
Q_EMIT countChanged();
|
||||||
|
@ -86,8 +91,8 @@ void BooksPathModel::setPath(QString aPath)
|
||||||
iList[i].iName = newNames.at(i);
|
iList[i].iName = newNames.at(i);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (iList.at(i).iPath != newPaths.at(i)) {
|
if (iList.at(i).iPath != pathList.at(i)) {
|
||||||
iList[i].iPath = newPaths.at(i);
|
iList[i].iPath = pathList.at(i);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
@ -99,6 +104,20 @@ void BooksPathModel::setPath(QString aPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BooksPathModel::setStorage(QObject* aStorage)
|
||||||
|
{
|
||||||
|
BooksStorage storage;
|
||||||
|
if (aStorage) {
|
||||||
|
BooksStorage* newStorage = qobject_cast<BooksStorage*>(aStorage);
|
||||||
|
if (newStorage) storage.set(*newStorage);
|
||||||
|
}
|
||||||
|
if (!iStorage.equal(storage)) {
|
||||||
|
HDEBUG(storage.booksDir());
|
||||||
|
iStorage.set(storage);
|
||||||
|
Q_EMIT storageChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QHash<int,QByteArray> BooksPathModel::roleNames() const
|
QHash<int,QByteArray> BooksPathModel::roleNames() const
|
||||||
{
|
{
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
|
@ -123,3 +142,30 @@ QVariant BooksPathModel::data(const QModelIndex& aIndex, int aRole) const
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BooksPathModel::setData(const QModelIndex& aIndex, const QVariant& aValue, int aRole)
|
||||||
|
{
|
||||||
|
const int i = aIndex.row();
|
||||||
|
if (validIndex(i) && aRole == BooksPathModelName && iStorage.isPresent()) {
|
||||||
|
QString newName(aValue.toString());
|
||||||
|
if (iList.at(i).iName != newName) {
|
||||||
|
const Data& data = iList.at(i);
|
||||||
|
QString oldPath = iStorage.fullPath(data.iPath);
|
||||||
|
QString newPath = iStorage.fullPath(data.iParentPath);
|
||||||
|
newPath += "/";
|
||||||
|
newPath += newName;
|
||||||
|
|
||||||
|
HDEBUG("renaming" << qPrintable(oldPath) << "->" << qPrintable(newPath));
|
||||||
|
if (rename(qPrintable(oldPath), qPrintable(newPath)) == 0) {
|
||||||
|
iList[i].iName = newName;
|
||||||
|
iList[i].iPath = newPath;
|
||||||
|
QModelIndex index = createIndex(i, 0);
|
||||||
|
Q_EMIT dataChanged(index, index);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
HDEBUG(strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#define BOOKS_PATH_MODEL_H
|
#define BOOKS_PATH_MODEL_H
|
||||||
|
|
||||||
#include "BooksTypes.h"
|
#include "BooksTypes.h"
|
||||||
|
#include "BooksStorage.h"
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
@ -47,6 +48,7 @@ class BooksPathModel: public QAbstractListModel
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||||
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
|
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
|
||||||
|
Q_PROPERTY(QObject* storage READ storage WRITE setStorage NOTIFY storageChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BooksPathModel(QObject* aParent = NULL);
|
explicit BooksPathModel(QObject* aParent = NULL);
|
||||||
|
@ -54,15 +56,19 @@ public:
|
||||||
int count() const { return iList.count(); }
|
int count() const { return iList.count(); }
|
||||||
QString path() const { return iPath; }
|
QString path() const { return iPath; }
|
||||||
void setPath(QString aPath);
|
void setPath(QString aPath);
|
||||||
|
QObject* storage() { return &iStorage; }
|
||||||
|
void setStorage(QObject* aStorage);
|
||||||
|
|
||||||
// QAbstractListModel
|
// QAbstractListModel
|
||||||
virtual QHash<int,QByteArray> roleNames() const;
|
virtual QHash<int,QByteArray> roleNames() const;
|
||||||
virtual int rowCount(const QModelIndex& aParent) const;
|
virtual int rowCount(const QModelIndex& aParent) const;
|
||||||
virtual QVariant data(const QModelIndex& aIndex, int aRole) const;
|
virtual QVariant data(const QModelIndex& aIndex, int aRole) const;
|
||||||
|
virtual bool setData(const QModelIndex& aIndex, const QVariant& aValue, int aRole);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void countChanged();
|
void countChanged();
|
||||||
void pathChanged();
|
void pathChanged();
|
||||||
|
void storageChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool validIndex(int aIndex) const;
|
bool validIndex(int aIndex) const;
|
||||||
|
@ -70,10 +76,14 @@ private:
|
||||||
private:
|
private:
|
||||||
class Data {
|
class Data {
|
||||||
public:
|
public:
|
||||||
QString iName;
|
QString iParentPath;
|
||||||
QString iPath;
|
QString iPath;
|
||||||
Data(QString aName, QString aPath) : iName(aName), iPath(aPath) {}
|
QString iName;
|
||||||
|
Data(QString aParentPath, QString aPath, QString aName) :
|
||||||
|
iParentPath(aParentPath), iPath(aPath), iName(aName) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BooksStorage iStorage;
|
||||||
QList<Data> iList;
|
QList<Data> iList;
|
||||||
QString iPath;
|
QString iPath;
|
||||||
};
|
};
|
||||||
|
|
|
@ -227,14 +227,13 @@ bool BooksStorage::equal(const BooksStorage& aStorage) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BooksStorage& BooksStorage::operator = (const BooksStorage& aStorage)
|
void BooksStorage::set(const BooksStorage& aStorage)
|
||||||
{
|
{
|
||||||
if (iPrivate != aStorage.iPrivate) {
|
if (iPrivate != aStorage.iPrivate) {
|
||||||
if (iPrivate && !iPrivate->iRef.deref()) delete iPrivate;
|
if (iPrivate && !iPrivate->iRef.deref()) delete iPrivate;
|
||||||
iPrivate = aStorage.iPrivate;
|
iPrivate = aStorage.iPrivate;
|
||||||
if (iPrivate) iPrivate->iRef.ref();
|
if (iPrivate) iPrivate->iRef.ref();
|
||||||
}
|
}
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
|
@ -64,8 +64,10 @@ public:
|
||||||
bool isInternal() const;
|
bool isInternal() const;
|
||||||
bool isPresent() const;
|
bool isPresent() const;
|
||||||
bool equal(const BooksStorage& aStorage) const;
|
bool equal(const BooksStorage& aStorage) const;
|
||||||
|
void set(const BooksStorage& aStorage);
|
||||||
|
|
||||||
BooksStorage& operator = (const BooksStorage& aStorage);
|
BooksStorage& operator = (const BooksStorage& aStorage)
|
||||||
|
{ set(aStorage); return *this; }
|
||||||
bool operator == (const BooksStorage& aStorage) const
|
bool operator == (const BooksStorage& aStorage) const
|
||||||
{ return equal(aStorage); }
|
{ return equal(aStorage); }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue