[app] Implemented folder renaming

This commit is contained in:
Slava Monich 2015-11-30 17:57:27 +02:00
parent 8a4e131452
commit 57204d3cc4
7 changed files with 129 additions and 61 deletions

View file

@ -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()

View file

@ -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
}
} }
} }
} }

View file

@ -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
} }

View file

@ -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;
}

View file

@ -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;
}; };

View file

@ -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;
} }
// ========================================================================== // ==========================================================================

View file

@ -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); }