[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
|
||||
property alias text: label.text
|
||||
property bool currentFolder
|
||||
property bool editable
|
||||
property bool _editing
|
||||
property bool _highlighted: pressed
|
||||
property color _highlightedColor: Theme.rgba(Theme.highlightBackgroundColor, Theme.highlightBackgroundOpacity)
|
||||
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 {
|
||||
id: column
|
||||
width: parent.width
|
||||
|
@ -52,8 +69,7 @@ MouseArea {
|
|||
}
|
||||
|
||||
Item {
|
||||
id: labelItem
|
||||
width: Math.min(label.implicitWidth + icon.width + 3*Theme.paddingMedium, parent.width)
|
||||
width: parent.width
|
||||
height: label.implicitHeight
|
||||
|
||||
Image {
|
||||
|
@ -72,66 +88,53 @@ MouseArea {
|
|||
Label {
|
||||
id: label
|
||||
truncationMode: TruncationMode.Fade
|
||||
width: Math.min(parent.width - 2*Theme.paddingMedium, implicitWidth)
|
||||
anchors {
|
||||
left: icon.right
|
||||
leftMargin: Theme.paddingMedium
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
onTextChanged: {
|
||||
if (!_editing) {
|
||||
editor.text = text
|
||||
}
|
||||
}
|
||||
color: (currentFolder || pressed) ? Theme.highlightColor : Theme.primaryColor
|
||||
opacity: _editing ? 0 : 1
|
||||
visible: opacity > 0
|
||||
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 {
|
||||
height: Theme.paddingSmall
|
||||
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()
|
||||
|
|
|
@ -75,6 +75,7 @@ SilicaFlickable {
|
|||
BooksPathModel {
|
||||
id: pathModel
|
||||
path: shelfModel.relativePath
|
||||
storage: shelfModel.storage
|
||||
}
|
||||
|
||||
onEditModeChanged: {
|
||||
|
@ -175,17 +176,24 @@ SilicaFlickable {
|
|||
BooksShelfTitle {
|
||||
width: grid.width
|
||||
text: model.name
|
||||
editable: editMode
|
||||
currentFolder: model.index === (pathModel.count-1)
|
||||
onClicked: {
|
||||
if (currentFolder) {
|
||||
if (editMode) {
|
||||
console.log("how about renaming", model.name)
|
||||
console.log("editing", model.name)
|
||||
editName()
|
||||
}
|
||||
} else {
|
||||
console.log("switching to", model.path)
|
||||
shelfView.stopEditing()
|
||||
shelfModel.relativePath = model.path
|
||||
}
|
||||
}
|
||||
onRename: {
|
||||
console.log(to)
|
||||
model.name = to
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,8 +74,8 @@ SilicaFlickable {
|
|||
|
||||
function calculateCellWidth() {
|
||||
// At least 3 books in portrait, 5 in landscape
|
||||
var result2 = calculateCellWidth2(Math.min(width, height), 3)
|
||||
var result1 = calculateCellWidth2(Math.max(width, height), 5)
|
||||
var result2 = calculateCellWidth2(Math.min(window.width, window.height), 3)
|
||||
var result1 = calculateCellWidth2(Math.max(window.width, window.height), 5)
|
||||
var result = Math.min(result1, result2)
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
#include "HarbourDebug.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
enum BooksPathModelRole {
|
||||
BooksPathModelName = Qt::UserRole,
|
||||
BooksPathModelPath
|
||||
|
@ -60,17 +62,20 @@ void BooksPathModel::setPath(QString aPath)
|
|||
|
||||
int i;
|
||||
QString path;
|
||||
QStringList newPaths;
|
||||
QStringList pathList;
|
||||
QStringList parentList;
|
||||
for (i=0; i<newSize; i++) {
|
||||
parentList.append(path);
|
||||
if (!path.isEmpty()) path += "/";
|
||||
path += newNames.at(i);
|
||||
newPaths.append(path);
|
||||
pathList.append(path);
|
||||
}
|
||||
|
||||
if (oldSize < newSize) {
|
||||
beginInsertRows(QModelIndex(), oldSize, newSize-1);
|
||||
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();
|
||||
Q_EMIT countChanged();
|
||||
|
@ -86,8 +91,8 @@ void BooksPathModel::setPath(QString aPath)
|
|||
iList[i].iName = newNames.at(i);
|
||||
changed = true;
|
||||
}
|
||||
if (iList.at(i).iPath != newPaths.at(i)) {
|
||||
iList[i].iPath = newPaths.at(i);
|
||||
if (iList.at(i).iPath != pathList.at(i)) {
|
||||
iList[i].iPath = pathList.at(i);
|
||||
changed = true;
|
||||
}
|
||||
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> roles;
|
||||
|
@ -123,3 +142,30 @@ QVariant BooksPathModel::data(const QModelIndex& aIndex, int aRole) const
|
|||
}
|
||||
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
|
||||
|
||||
#include "BooksTypes.h"
|
||||
#include "BooksStorage.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QVariant>
|
||||
|
@ -47,6 +48,7 @@ class BooksPathModel: public QAbstractListModel
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
|
||||
Q_PROPERTY(QObject* storage READ storage WRITE setStorage NOTIFY storageChanged)
|
||||
|
||||
public:
|
||||
explicit BooksPathModel(QObject* aParent = NULL);
|
||||
|
@ -54,15 +56,19 @@ public:
|
|||
int count() const { return iList.count(); }
|
||||
QString path() const { return iPath; }
|
||||
void setPath(QString aPath);
|
||||
QObject* storage() { return &iStorage; }
|
||||
void setStorage(QObject* aStorage);
|
||||
|
||||
// QAbstractListModel
|
||||
virtual QHash<int,QByteArray> roleNames() const;
|
||||
virtual int rowCount(const QModelIndex& aParent) const;
|
||||
virtual QVariant data(const QModelIndex& aIndex, int aRole) const;
|
||||
virtual bool setData(const QModelIndex& aIndex, const QVariant& aValue, int aRole);
|
||||
|
||||
Q_SIGNALS:
|
||||
void countChanged();
|
||||
void pathChanged();
|
||||
void storageChanged();
|
||||
|
||||
private:
|
||||
bool validIndex(int aIndex) const;
|
||||
|
@ -70,10 +76,14 @@ private:
|
|||
private:
|
||||
class Data {
|
||||
public:
|
||||
QString iName;
|
||||
QString iParentPath;
|
||||
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;
|
||||
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 && !iPrivate->iRef.deref()) delete iPrivate;
|
||||
iPrivate = aStorage.iPrivate;
|
||||
if (iPrivate) iPrivate->iRef.ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ==========================================================================
|
||||
|
|
|
@ -64,8 +64,10 @@ public:
|
|||
bool isInternal() const;
|
||||
bool isPresent() 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
|
||||
{ return equal(aStorage); }
|
||||
|
||||
|
|
Loading…
Reference in a new issue