Improve coding style

This commit is contained in:
Martchus 2018-03-14 00:15:12 +01:00
parent 3590a5150c
commit 836e6bbcb2
11 changed files with 536 additions and 533 deletions

View File

@ -9,7 +9,7 @@ class FieldDelegate : public QStyledItemDelegate {
public: public:
FieldDelegate(QObject *parent = nullptr); FieldDelegate(QObject *parent = nullptr);
void setEditorData(QWidget *editor, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const override;
}; };
} // namespace QtGui } // namespace QtGui

View File

@ -440,13 +440,11 @@ bool MainWindow::openFile(const QString &path, bool readOnly)
} }
// warn before loading a very big file // warn before loading a very big file
if (m_file.size() > 10485760) { if (m_file.size() > 10485760 && QMessageBox::warning(this, QApplication::applicationName(),
if (QMessageBox::warning(this, QApplication::applicationName(),
tr("The file you want to load seems to be very big. Do you really want to open it?"), QMessageBox::Yes, QMessageBox::No) tr("The file you want to load seems to be very big. Do you really want to open it?"), QMessageBox::Yes, QMessageBox::No)
== QMessageBox::No) { == QMessageBox::No) {
m_file.clear(); m_file.clear();
return false; return false;
}
} }
// ask for a password if required // ask for a password if required
@ -488,18 +486,17 @@ bool MainWindow::openFile(const QString &path, bool readOnly)
} }
// show a message in the error case // show a message in the error case
if (!msg.isEmpty()) { if (msg.isEmpty()) {
m_file.clear();
m_ui->statusBar->showMessage(msg, 5000);
if (QMessageBox::critical(this, QApplication::applicationName(), msg, QMessageBox::Cancel, QMessageBox::Retry) == QMessageBox::Retry) {
return openFile(path, readOnly); // retry
} else {
return false;
}
} else {
// show contents // show contents
return showFile(); return showFile();
} }
m_file.clear();
m_ui->statusBar->showMessage(msg, 5000);
if (QMessageBox::critical(this, QApplication::applicationName(), msg, QMessageBox::Cancel, QMessageBox::Retry) == QMessageBox::Retry) {
return openFile(path, readOnly); // retry
} else {
return false;
}
} }
/*! /*!
@ -618,7 +615,7 @@ void MainWindow::updateWindowTitle()
void MainWindow::applyDefaultExpanding(const QModelIndex &parent) void MainWindow::applyDefaultExpanding(const QModelIndex &parent)
{ {
for (int row = 0, rows = m_entryFilterModel->rowCount(parent); row < rows; ++row) { for (int row = 0, rows = m_entryFilterModel->rowCount(parent); row < rows; ++row) {
QModelIndex index = m_entryFilterModel->index(row, 0, parent); const QModelIndex index = m_entryFilterModel->index(row, 0, parent);
if (!index.isValid()) { if (!index.isValid()) {
return; return;
} }
@ -735,7 +732,7 @@ bool MainWindow::askForCreatingFile()
/*! /*!
* \brief Shows an warning if no file is opened. * \brief Shows an warning if no file is opened.
* \retruns Returns whether the warning has been shown. * \returns Returns whether the warning has been shown.
*/ */
bool MainWindow::showNoFileOpened() bool MainWindow::showNoFileOpened()
{ {
@ -748,7 +745,7 @@ bool MainWindow::showNoFileOpened()
/*! /*!
* \brief Shows an warning if no account is selected. * \brief Shows an warning if no account is selected.
* \retruns Returns whether the warning has been shown. * \returns Returns whether the warning has been shown.
*/ */
bool MainWindow::showNoAccount() bool MainWindow::showNoAccount()
{ {
@ -821,10 +818,8 @@ bool MainWindow::saveFile()
return false; return false;
} }
} }
} else { } else if (!askForCreatingFile()) {
if (!askForCreatingFile()) { return false;
return false;
}
} }
// ask for a password if none is set // ask for a password if none is set
@ -858,16 +853,15 @@ bool MainWindow::saveFile()
m_ui->statusBar->showMessage(msg, 5000); m_ui->statusBar->showMessage(msg, 5000);
QMessageBox::critical(this, QApplication::applicationName(), msg); QMessageBox::critical(this, QApplication::applicationName(), msg);
return false; return false;
} else {
if (m_readOnly || m_somethingChanged) {
m_readOnly = false;
m_somethingChanged = false;
updateWindowTitle();
}
m_recentMgr->addEntry(QString::fromStdString(m_file.path()));
m_ui->statusBar->showMessage(tr("The password list has been saved."), 5000);
return true;
} }
if (m_readOnly || m_somethingChanged) {
m_readOnly = false;
m_somethingChanged = false;
updateWindowTitle();
}
m_recentMgr->addEntry(QString::fromStdString(m_file.path()));
m_ui->statusBar->showMessage(tr("The password list has been saved."), 5000);
return true;
} }
/*! /*!
@ -904,13 +898,14 @@ void MainWindow::showContainingDirectory()
{ {
if (showNoFileOpened()) { if (showNoFileOpened()) {
return; return;
} else if (m_file.path().empty()) { }
if (m_file.path().empty()) {
QMessageBox::warning(this, QApplication::applicationName(), tr("The currently opened file hasn't been saved yet.")); QMessageBox::warning(this, QApplication::applicationName(), tr("The currently opened file hasn't been saved yet."));
} else { return;
const QFileInfo file(QString::fromStdString(m_file.path())); }
if (file.dir().exists()) { const QFileInfo file(QString::fromStdString(m_file.path()));
DesktopUtils::openLocalFileOrDir(file.dir().absolutePath()); if (file.dir().exists()) {
} DesktopUtils::openLocalFileOrDir(file.dir().absolutePath());
} }
} }
@ -941,30 +936,29 @@ void MainWindow::addEntry(EntryType type)
return; return;
} }
const QModelIndexList selectedIndexes = m_ui->treeView->selectionModel()->selectedRows(0); const QModelIndexList selectedIndexes = m_ui->treeView->selectionModel()->selectedRows(0);
if (selectedIndexes.size() == 1) { const QModelIndex selected = selectedIndexes.size() == 1 ? m_entryFilterModel->mapToSource(selectedIndexes.at(0)) : QModelIndex();
const QModelIndex selected = m_entryFilterModel->mapToSource(selectedIndexes.at(0)); if (!selected.isValid() || !m_entryModel->isNode(selected)) {
if (m_entryModel->isNode(selected)) { QMessageBox::warning(this, QApplication::applicationName(), tr("No node element selected."));
bool result; return;
const QString text = QInputDialog::getText(this, type == EntryType::Account ? tr("Add account") : tr("Add category"),
tr("Enter the entry name"), QLineEdit::Normal, tr("new entry"), &result);
if (result) {
if (!text.isEmpty()) {
int row = m_entryModel->rowCount(selected);
m_entryModel->setInsertType(type);
if (m_entryModel->insertRow(row, selected)) {
m_entryModel->setData(m_entryModel->index(row, 0, selected), text, Qt::DisplayRole);
setSomethingChanged(true);
} else {
QMessageBox::warning(this, QApplication::applicationName(), tr("Unable to create new entry."));
}
} else {
QMessageBox::warning(this, QApplication::applicationName(), tr("You didn't enter text."));
}
}
return;
}
} }
QMessageBox::warning(this, QApplication::applicationName(), tr("No node element selected.")); bool result;
const QString text = QInputDialog::getText(this, type == EntryType::Account ? tr("Add account") : tr("Add category"),
tr("Enter the entry name"), QLineEdit::Normal, tr("new entry"), &result);
if (!result) {
return;
}
if (text.isEmpty()) {
QMessageBox::warning(this, QApplication::applicationName(), tr("You didn't enter text."));
return;
}
int row = m_entryModel->rowCount(selected);
m_entryModel->setInsertType(type);
if (!m_entryModel->insertRow(row, selected)) {
QMessageBox::warning(this, QApplication::applicationName(), tr("Unable to create new entry."));
return;
}
m_entryModel->setData(m_entryModel->index(row, 0, selected), text, Qt::DisplayRole);
setSomethingChanged(true);
} }
/*! /*!
@ -976,13 +970,13 @@ void MainWindow::removeEntry()
return; return;
} }
const QModelIndexList selectedIndexes = m_ui->treeView->selectionModel()->selectedRows(0); const QModelIndexList selectedIndexes = m_ui->treeView->selectionModel()->selectedRows(0);
if (selectedIndexes.size() == 1) { if (selectedIndexes.size() != 1) {
const QModelIndex selected = m_entryFilterModel->mapToSource(selectedIndexes.at(0));
if (!m_entryModel->removeRow(selected.row(), selected.parent())) {
QMessageBox::warning(this, QApplication::applicationName(), tr("Unable to remove the entry."));
}
} else {
QMessageBox::warning(this, QApplication::applicationName(), tr("No entry selected.")); QMessageBox::warning(this, QApplication::applicationName(), tr("No entry selected."));
return;
}
const QModelIndex selected = m_entryFilterModel->mapToSource(selectedIndexes.at(0));
if (!m_entryModel->removeRow(selected.row(), selected.parent())) {
QMessageBox::warning(this, QApplication::applicationName(), tr("Unable to remove the entry."));
} }
} }
@ -1023,19 +1017,19 @@ void MainWindow::insertRow()
return; return;
} }
const QModelIndexList selectedIndexes = m_ui->tableView->selectionModel()->selectedIndexes(); const QModelIndexList selectedIndexes = m_ui->tableView->selectionModel()->selectedIndexes();
if (selectedIndexes.size()) { if (selectedIndexes.empty()) {
int row = m_fieldModel->rowCount();
for (const QModelIndex &index : selectedIndexes) {
if (index.row() < row) {
row = index.row();
}
}
if (row < m_fieldModel->rowCount() - 1) {
m_fieldModel->insertRow(row);
}
} else {
QMessageBox::warning( QMessageBox::warning(
this, windowTitle(), tr("A field has to be selected since new fields are always inserted before the currently selected field.")); this, windowTitle(), tr("A field has to be selected since new fields are always inserted before the currently selected field."));
return;
}
int row = m_fieldModel->rowCount();
for (const QModelIndex &index : selectedIndexes) {
if (index.row() < row) {
row = index.row();
}
}
if (row < m_fieldModel->rowCount() - 1) {
m_fieldModel->insertRow(row);
} }
} }
@ -1052,14 +1046,14 @@ void MainWindow::removeRows()
for (const QModelIndex &index : selectedIndexes) { for (const QModelIndex &index : selectedIndexes) {
rows << index.row(); rows << index.row();
} }
if (rows.size()) { if (rows.empty()) {
for (int i = m_fieldModel->rowCount() - 1; i >= 0; --i) {
if (rows.contains(i)) {
m_fieldModel->removeRow(i);
}
}
} else {
QMessageBox::warning(this, windowTitle(), tr("No fields have been removed since there are currently no fields selected.")); QMessageBox::warning(this, windowTitle(), tr("No fields have been removed since there are currently no fields selected."));
return;
}
for (int i = m_fieldModel->rowCount() - 1; i >= 0; --i) {
if (rows.contains(i)) {
m_fieldModel->removeRow(i);
}
} }
} }
@ -1088,13 +1082,13 @@ void MainWindow::setFieldType(FieldType fieldType)
return; return;
} }
const QModelIndexList selectedIndexes = m_ui->tableView->selectionModel()->selectedIndexes(); const QModelIndexList selectedIndexes = m_ui->tableView->selectionModel()->selectedIndexes();
if (!selectedIndexes.isEmpty()) { if (selectedIndexes.isEmpty()) {
const QVariant typeVariant(static_cast<int>(fieldType));
for (const QModelIndex &index : selectedIndexes) {
m_fieldModel->setData(index, typeVariant, FieldTypeRole);
}
} else {
QMessageBox::warning(this, windowTitle(), tr("No fields have been changed since there are currently no fields selected.")); QMessageBox::warning(this, windowTitle(), tr("No fields have been changed since there are currently no fields selected."));
return;
}
const QVariant typeVariant(static_cast<int>(fieldType));
for (const QModelIndex &index : selectedIndexes) {
m_fieldModel->setData(index, typeVariant, FieldTypeRole);
} }
} }
@ -1154,28 +1148,29 @@ void MainWindow::showTreeViewContextMenu()
return; return;
} }
const QModelIndexList selectedIndexes = m_ui->treeView->selectionModel()->selectedRows(0); const QModelIndexList selectedIndexes = m_ui->treeView->selectionModel()->selectedRows(0);
if (selectedIndexes.size() == 1) { if (selectedIndexes.size() != 1) {
QMenu contextMenu(this); return;
QModelIndex selected = m_entryFilterModel->mapToSource(selectedIndexes.at(0));
Entry *entry = m_entryModel->entry(selected);
if (entry->type() == EntryType::Node) {
contextMenu.addAction(QIcon::fromTheme(QStringLiteral("list-add")), tr("Add account"), this, &MainWindow::addAccount);
contextMenu.addAction(QIcon::fromTheme(QStringLiteral("list-add")), tr("Add category"), this, &MainWindow::addCategory);
}
contextMenu.addAction(QIcon::fromTheme(QStringLiteral("list-remove")), tr("Remove entry"), this, &MainWindow::removeEntry);
if (entry->type() == EntryType::Node) {
auto *nodeEntry = static_cast<NodeEntry *>(entry);
contextMenu.addSeparator();
auto *action = new QAction(&contextMenu);
action->setCheckable(true);
action->setText(tr("Expanded by default"));
action->setChecked(nodeEntry->isExpandedByDefault());
connect(action, &QAction::triggered,
std::bind(&EntryModel::setData, m_entryModel, std::cref(selected), QVariant(!nodeEntry->isExpandedByDefault()), DefaultExpandedRole));
contextMenu.addAction(action);
}
contextMenu.exec(QCursor::pos());
} }
QMenu contextMenu(this);
const QModelIndex selected(m_entryFilterModel->mapToSource(selectedIndexes.at(0)));
const Entry *const entry = m_entryModel->entry(selected);
if (entry->type() == EntryType::Node) {
contextMenu.addAction(QIcon::fromTheme(QStringLiteral("list-add")), tr("Add account"), this, &MainWindow::addAccount);
contextMenu.addAction(QIcon::fromTheme(QStringLiteral("list-add")), tr("Add category"), this, &MainWindow::addCategory);
}
contextMenu.addAction(QIcon::fromTheme(QStringLiteral("list-remove")), tr("Remove entry"), this, &MainWindow::removeEntry);
if (entry->type() == EntryType::Node) {
const auto *const nodeEntry = static_cast<const NodeEntry *>(entry);
contextMenu.addSeparator();
auto *const action = new QAction(&contextMenu);
action->setCheckable(true);
action->setText(tr("Expanded by default"));
action->setChecked(nodeEntry->isExpandedByDefault());
connect(action, &QAction::triggered,
std::bind(&EntryModel::setData, m_entryModel, std::cref(selected), QVariant(!nodeEntry->isExpandedByDefault()), DefaultExpandedRole));
contextMenu.addAction(action);
}
contextMenu.exec(QCursor::pos());
} }
/*! /*!

View File

@ -49,7 +49,7 @@ class MainWindow : public QMainWindow {
public: public:
explicit MainWindow(QSettings &settings, Dialogs::QtSettings *qtSettings = nullptr, QWidget *parent = nullptr); explicit MainWindow(QSettings &settings, Dialogs::QtSettings *qtSettings = nullptr, QWidget *parent = nullptr);
~MainWindow(); ~MainWindow() override;
public slots: public slots:
// file management // file management
@ -71,9 +71,9 @@ public slots:
void showUndoView(); void showUndoView();
protected: protected:
bool eventFilter(QObject *obj, QEvent *event); bool eventFilter(QObject *obj, QEvent *event) override;
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event) override;
void timerEvent(QTimerEvent *event); void timerEvent(QTimerEvent *event) override;
private slots: private slots:
// file management // file management

View File

@ -70,7 +70,6 @@ PasswordGeneratorDialog::PasswordGeneratorDialog(QWidget *parent)
*/ */
PasswordGeneratorDialog::~PasswordGeneratorDialog() PasswordGeneratorDialog::~PasswordGeneratorDialog()
{ {
delete m_ui;
} }
/*! /*!

View File

@ -6,6 +6,7 @@
#include <QDialog> #include <QDialog>
#include <vector> #include <vector>
#include <memory>
namespace QtGui { namespace QtGui {
@ -18,7 +19,7 @@ class PasswordGeneratorDialog : public QDialog {
public: public:
explicit PasswordGeneratorDialog(QWidget *parent = nullptr); explicit PasswordGeneratorDialog(QWidget *parent = nullptr);
~PasswordGeneratorDialog(); ~PasswordGeneratorDialog() override;
private Q_SLOTS: private Q_SLOTS:
void generateNewPassword(); void generateNewPassword();
@ -27,7 +28,7 @@ private Q_SLOTS:
void copyPassword(); void copyPassword();
private: private:
Ui::PasswordGeneratorDialog *m_ui; std::unique_ptr<Ui::PasswordGeneratorDialog> m_ui;
std::vector<char> m_charset; std::vector<char> m_charset;
Util::OpenSslRandomDevice m_random; Util::OpenSslRandomDevice m_random;
}; };

View File

@ -37,15 +37,14 @@ inline QUndoStack *StackSupport::undoStack()
*/ */
inline bool StackSupport::push(CustomUndoCommand *command) inline bool StackSupport::push(CustomUndoCommand *command)
{ {
if (m_undoStack) { if (!m_undoStack) {
if (command->isNoop()) { return false;
return true; // doing nothing can never fail
} else {
m_undoStack->push(command);
return command->redoResult();
}
} }
return false; if (command->isNoop()) {
return true; // doing nothing can never fail
}
m_undoStack->push(command);
return command->redoResult();
} }
/*! /*!

View File

@ -132,7 +132,7 @@ FieldModelInsertRowsCommand::FieldModelInsertRowsCommand(FieldModel *model, int
, m_row(row) , m_row(row)
, m_count(count) , m_count(count)
{ {
setText(QApplication::translate("undocommands", "insertion of %1 row(s) before row %2", 0, count).arg(count).arg(row + 1)); setText(QApplication::translate("undocommands", "insertion of %1 row(s) before row %2", nullptr, count).arg(count).arg(row + 1));
} }
bool FieldModelInsertRowsCommand::internalRedo() bool FieldModelInsertRowsCommand::internalRedo()
@ -163,9 +163,9 @@ FieldModelRemoveRowsCommand::FieldModelRemoveRowsCommand(FieldModel *model, int
, m_count(count) , m_count(count)
{ {
if (count == 1) { if (count == 1) {
setText(QApplication::translate("undocommands", "removal of row %1", 0, count).arg(row + 1)); setText(QApplication::translate("undocommands", "removal of row %1", nullptr, count).arg(row + 1));
} else { } else {
setText(QApplication::translate("undocommands", "removal of the rows %1 to %2", 0, count).arg(row + 1).arg(row + count)); setText(QApplication::translate("undocommands", "removal of the rows %1 to %2", nullptr, count).arg(row + 1).arg(row + count));
} }
} }

View File

@ -27,8 +27,8 @@ public:
bool redoResult() const; bool redoResult() const;
bool undoResult() const; bool undoResult() const;
bool isNoop() const; bool isNoop() const;
void redo(); void redo() override;
void undo(); void undo() override;
protected: protected:
void setNoop(bool noop); void setNoop(bool noop);
@ -81,8 +81,8 @@ public:
explicit FieldModelSetValueCommand(FieldModel *model, const QModelIndex &index, const QVariant &value, int role); explicit FieldModelSetValueCommand(FieldModel *model, const QModelIndex &index, const QVariant &value, int role);
protected: protected:
bool internalRedo(); bool internalRedo() override;
bool internalUndo(); bool internalUndo() override;
private: private:
Io::AccountEntry *m_account; Io::AccountEntry *m_account;
@ -99,8 +99,8 @@ public:
explicit FieldModelInsertRowsCommand(FieldModel *model, int row, int count); explicit FieldModelInsertRowsCommand(FieldModel *model, int row, int count);
protected: protected:
bool internalRedo(); bool internalRedo() override;
bool internalUndo(); bool internalUndo() override;
private: private:
Io::AccountEntry *m_account; Io::AccountEntry *m_account;
@ -114,8 +114,8 @@ public:
explicit FieldModelRemoveRowsCommand(FieldModel *model, int row, int count); explicit FieldModelRemoveRowsCommand(FieldModel *model, int row, int count);
protected: protected:
bool internalRedo(); bool internalRedo() override;
bool internalUndo(); bool internalUndo() override;
private: private:
Io::AccountEntry *m_account; Io::AccountEntry *m_account;
@ -130,8 +130,8 @@ public:
explicit EntryModelSetValueCommand(EntryModel *model, const QModelIndex &index, const QVariant &value, int role); explicit EntryModelSetValueCommand(EntryModel *model, const QModelIndex &index, const QVariant &value, int role);
protected: protected:
bool internalRedo(); bool internalRedo() override;
bool internalUndo(); bool internalUndo() override;
private: private:
EntryModel *m_model; EntryModel *m_model;
@ -143,12 +143,10 @@ private:
class EntryModelModifyRowsCommand : public CustomUndoCommand { class EntryModelModifyRowsCommand : public CustomUndoCommand {
public: public:
~EntryModelModifyRowsCommand(); ~EntryModelModifyRowsCommand() override;
protected: protected:
explicit EntryModelModifyRowsCommand(EntryModel *model, int row, int count, const QModelIndex &parent); explicit EntryModelModifyRowsCommand(EntryModel *model, int row, int count, const QModelIndex &parent);
bool internalRedo() = 0;
bool internalUndo() = 0;
bool insert(); bool insert();
bool remove(); bool remove();
EntryModel *m_model; EntryModel *m_model;
@ -163,8 +161,8 @@ public:
explicit EntryModelInsertRowsCommand(EntryModel *model, int row, int count, const QModelIndex &parent); explicit EntryModelInsertRowsCommand(EntryModel *model, int row, int count, const QModelIndex &parent);
protected: protected:
bool internalRedo(); bool internalRedo() override;
bool internalUndo(); bool internalUndo() override;
}; };
class EntryModelRemoveRowsCommand : public EntryModelModifyRowsCommand { class EntryModelRemoveRowsCommand : public EntryModelModifyRowsCommand {
@ -172,8 +170,8 @@ public:
explicit EntryModelRemoveRowsCommand(EntryModel *model, int row, int count, const QModelIndex &parent); explicit EntryModelRemoveRowsCommand(EntryModel *model, int row, int count, const QModelIndex &parent);
protected: protected:
bool internalRedo(); bool internalRedo() override;
bool internalUndo(); bool internalUndo() override;
}; };
class EntryModelMoveRowsCommand : public CustomUndoCommand { class EntryModelMoveRowsCommand : public CustomUndoCommand {
@ -182,8 +180,8 @@ public:
EntryModel *model, const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild); EntryModel *model, const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild);
protected: protected:
bool internalRedo(); bool internalRedo() override;
bool internalUndo(); bool internalUndo() override;
private: private:
EntryModel *m_model; EntryModel *m_model;

View File

@ -61,11 +61,7 @@ EntryModel::EntryModel(QUndoStack *undoStack, QObject *parent) :
*/ */
Entry *EntryModel::entry(const QModelIndex &index) Entry *EntryModel::entry(const QModelIndex &index)
{ {
if(index.isValid()) { return index.isValid() ? static_cast<Entry *>(index.internalPointer()) : nullptr;
return static_cast<Entry *>(index.internalPointer());
} else {
return nullptr;
}
} }
/*! /*!
@ -78,24 +74,24 @@ Entry *EntryModel::entry(const QModelIndex &index)
*/ */
QList<Entry *> EntryModel::takeEntries(int row, int count, const QModelIndex &parent) QList<Entry *> EntryModel::takeEntries(int row, int count, const QModelIndex &parent)
{ {
QList<Entry *> res; Entry *const parentEntry = entry(parent);
if(Entry *parentEntry = entry(parent)) { if(!parentEntry || parentEntry->type() != EntryType::Node) {
if(parentEntry->type() == EntryType::Node) { return QList<Entry *>();
NodeEntry *parentNodeEntry = static_cast<NodeEntry *>(parentEntry);
int lastIndex = row + count - 1;
const vector<Entry *> &children = parentNodeEntry->children();
if(lastIndex < 0 || static_cast<size_t>(lastIndex) >= children.size()) {
lastIndex = children.size() - 1;
}
beginRemoveRows(parent, row, lastIndex);
for(int index = lastIndex; index >= row; --index) {
Entry *child = children.at(index);
child->setParent(nullptr);
res << child;
}
endRemoveRows();
}
} }
QList<Entry *> res;
NodeEntry *const parentNodeEntry = static_cast<NodeEntry *>(parentEntry);
int lastIndex = row + count - 1;
const vector<Entry *> &children = parentNodeEntry->children();
if(lastIndex < 0 || static_cast<size_t>(lastIndex) >= children.size()) {
lastIndex = children.size() - 1;
}
beginRemoveRows(parent, row, lastIndex);
for(int index = lastIndex; index >= row; --index) {
Entry *const child = children[index];
child->setParent(nullptr);
res << child;
}
endRemoveRows();
return res; return res;
} }
@ -111,42 +107,45 @@ bool EntryModel::insertEntries(int row, const QModelIndex &parent, const QList<E
if(entries.isEmpty()) { if(entries.isEmpty()) {
return true; return true;
} }
if(Entry *parentEntry = entry(parent)) { Entry *const parentEntry = entry(parent);
if(parentEntry->type() == EntryType::Node) { if(!parentEntry || parentEntry->type() != EntryType::Node) {
NodeEntry *parentNodeEntry = static_cast<NodeEntry *>(parentEntry); return false;
const vector<Entry *> &children = parentNodeEntry->children();
if(row < 0 || static_cast<size_t>(row) > children.size()) {
row = children.size();
}
beginInsertRows(parent, row, row + entries.size() - 1);
foreach(Entry *entry, entries) {
entry->setParent(parentNodeEntry, row);
++row;
}
endInsertRows();
return true;
}
} }
return false; NodeEntry *const parentNodeEntry = static_cast<NodeEntry *>(parentEntry);
const vector<Entry *> &children = parentNodeEntry->children();
if(row < 0 || static_cast<size_t>(row) > children.size()) {
row = children.size();
}
beginInsertRows(parent, row, row + entries.size() - 1);
for(Entry *const entry : entries) {
entry->setParent(parentNodeEntry, row);
++row;
}
endInsertRows();
return true;
} }
QModelIndex EntryModel::index(int row, int column, const QModelIndex &parent) const QModelIndex EntryModel::index(int row, int column, const QModelIndex &parent) const
{ {
if(parent.isValid()) { if(!parent.isValid()) {
if(Entry *parentEntry = static_cast<Entry *>(parent.internalPointer())) { if(m_rootEntry && row == 0) {
switch(parentEntry->type()) { return createIndex(row, column, m_rootEntry);
case EntryType::Node: {
const std::vector<Entry *> &children = static_cast<NodeEntry *>(parentEntry)->children();
if(row >= 0 && static_cast<size_t>(row) < children.size()) {
return createIndex(row, column, children.at(row));
}
break;
} case EntryType::Account:
;
}
} }
} else if(m_rootEntry && row == 0) { return QModelIndex();
return createIndex(row, column, m_rootEntry); }
const auto *const parentEntry = static_cast<const Entry *>(parent.internalPointer());
if(!parentEntry) {
return QModelIndex();
}
switch(parentEntry->type()) {
case EntryType::Node: {
const std::vector<Entry *> &children = static_cast<const NodeEntry *>(parentEntry)->children();
if(row >= 0 && static_cast<size_t>(row) < children.size()) {
return createIndex(row, column, children[static_cast<size_t>(row)]);
}
break;
} case EntryType::Account:
;
} }
return QModelIndex(); return QModelIndex();
} }
@ -166,29 +165,27 @@ QModelIndex EntryModel::index(Entry *entry) const
QModelIndex EntryModel::parent(const QModelIndex &child) const QModelIndex EntryModel::parent(const QModelIndex &child) const
{ {
if(child.isValid()) { if(!child.isValid()) {
if(Entry *entry = static_cast<Entry *>(child.internalPointer())) { return QModelIndex();
NodeEntry *parent = entry->parent(); }
if(parent && (child.row() >= 0 && static_cast<size_t>(child.row()) < parent->children().size())) { const auto *const entry = static_cast<Entry *>(child.internalPointer());
return createIndex(parent->index() > 0 ? parent->index() : 0, 0, parent); if(!entry) {
} return QModelIndex();
} }
NodeEntry *const parent = entry->parent();
if(parent && (child.row() >= 0 && static_cast<size_t>(child.row()) < parent->children().size())) {
return createIndex(parent->index() > 0 ? parent->index() : 0, 0, parent);
} }
return QModelIndex(); return QModelIndex();
} }
bool EntryModel::hasChildren(const QModelIndex &parent) const bool EntryModel::hasChildren(const QModelIndex &parent) const
{ {
if(parent.isValid()) { if(!parent.isValid()) {
if(Entry *entry = static_cast<Entry *>(parent.internalPointer())) {
if(entry->type() == EntryType::Node) {
return static_cast<NodeEntry *>(entry)->children().size();
}
}
} else {
return true; return true;
} }
return false; const auto *const entry = static_cast<Entry *>(parent.internalPointer());
return entry && entry->type() == EntryType::Node && !static_cast<const NodeEntry *>(entry)->children().empty();
} }
/*! /*!
@ -197,63 +194,65 @@ bool EntryModel::hasChildren(const QModelIndex &parent) const
*/ */
bool EntryModel::isNode(const QModelIndex &parent) const bool EntryModel::isNode(const QModelIndex &parent) const
{ {
if(parent.isValid()) { if(!parent.isValid()) {
if(Entry *entry = static_cast<Entry *>(parent.internalPointer())) { return false;
return entry->type() == EntryType::Node;
}
} }
return false; const auto *const entry = static_cast<const Entry *>(parent.internalPointer());
return entry && entry->type() == EntryType::Node;
} }
QVariant EntryModel::data(const QModelIndex &index, int role) const QVariant EntryModel::data(const QModelIndex &index, int role) const
{ {
if(index.isValid()) { if(!index.isValid()) {
if(Entry *entry = static_cast<Entry *>(index.internalPointer())) { return QVariant();
switch(role) { }
case Qt::DisplayRole: const auto *const entry = static_cast<const Entry *>(index.internalPointer());
case Qt::EditRole: if(!entry) {
switch(index.column()) { return QVariant();
case 0: }
return QString::fromStdString(entry->label()); switch(role) {
default: case Qt::DisplayRole:
; case Qt::EditRole:
} switch(index.column()) {
break; case 0:
case Qt::DecorationRole: return QString::fromStdString(entry->label());
if(index.column() == 0 && entry->type() == EntryType::Node) { default:
static const QVariant folderIcon = QIcon::fromTheme(QStringLiteral("folder")); ;
return folderIcon; }
} break;
break; case Qt::DecorationRole:
case SerializedRole: { if(index.column() == 0 && entry->type() == EntryType::Node) {
stringstream ss(stringstream::in | stringstream::out | stringstream::binary); static const QVariant folderIcon = QIcon::fromTheme(QStringLiteral("folder"));
ss.exceptions(std::stringstream::failbit | std::stringstream::badbit); return folderIcon;
try { }
entry->make(ss); break;
string string = ss.str(); case SerializedRole: {
return QByteArray(string.data(), string.size()); stringstream ss(stringstream::in | stringstream::out | stringstream::binary);
} catch(...) { ss.exceptions(std::stringstream::failbit | std::stringstream::badbit);
IoUtilities::catchIoFailure(); try {
return false; entry->make(ss);
} const auto str(ss.str());
} return QByteArray(str.data(), str.size());
break; } catch(...) {
case DefaultExpandedRole: IoUtilities::catchIoFailure();
return entry->type() == EntryType::Node && static_cast<NodeEntry *>(entry)->isExpandedByDefault(); return false;
default:
;
} }
} }
break;
case DefaultExpandedRole:
return entry->type() == EntryType::Node && static_cast<const NodeEntry *>(entry)->isExpandedByDefault();
default:
;
} }
return QVariant(); return QVariant();
} }
QMap<int, QVariant> EntryModel::itemData(const QModelIndex &index) const QMap<int, QVariant> EntryModel::itemData(const QModelIndex &index) const
{ {
QMap<int, QVariant> roles; return QMap<int, QVariant>{
roles.insert(Qt::DisplayRole, data(index, Qt::DisplayRole)); {Qt::DisplayRole, data(index, Qt::DisplayRole)},
roles.insert(SerializedRole, data(index, SerializedRole)); {SerializedRole, data(index, SerializedRole)},
return roles; };
} }
bool EntryModel::setData(const QModelIndex &index, const QVariant &value, int role) bool EntryModel::setData(const QModelIndex &index, const QVariant &value, int role)
@ -263,60 +262,65 @@ bool EntryModel::setData(const QModelIndex &index, const QVariant &value, int ro
return push(new EntryModelSetValueCommand(this, index, value, role)); return push(new EntryModelSetValueCommand(this, index, value, role));
} }
#endif #endif
if(index.isValid()) { if(!index.isValid()) {
if(Entry *entry = static_cast<Entry *>(index.internalPointer())) { return false;
switch(role) { }
case Qt::DisplayRole: auto *const entry = static_cast<Entry *>(index.internalPointer());
case Qt::EditRole: if(!entry) {
switch(index.column()) { return false;
case 0: }
entry->setLabel(value.toString().toStdString()); switch(role) {
emit dataChanged(index, index, QVector<int>() << role); case Qt::DisplayRole:
return true; case Qt::EditRole:
default: switch(index.column()) {
; case 0:
} entry->setLabel(value.toString().toStdString());
emit dataChanged(index, index, QVector<int>() << role);
return true;
default:
;
}
break;
case SerializedRole: {
NodeEntry *parent = entry->parent();
QModelIndex parentIndex = index.parent();
if(!parent || !parentIndex.isValid()) {
break; break;
case SerializedRole: { }
NodeEntry *parent = entry->parent(); stringstream ss(stringstream::in | stringstream::out | stringstream::binary);
QModelIndex parentIndex = index.parent(); ss.exceptions(std::stringstream::failbit | std::stringstream::badbit);
if(parent && parentIndex.isValid()) { QByteArray array = value.toByteArray();
stringstream ss(stringstream::in | stringstream::out | stringstream::binary); if(array.isEmpty()) {
ss.exceptions(std::stringstream::failbit | std::stringstream::badbit);
QByteArray array = value.toByteArray();
if(array.size()) {
try {
ss.write(array.data(), array.size());
Entry *newEntry = Entry::parse(ss);
int row = entry->index();
beginRemoveRows(parentIndex, row, row);
delete entry;
endRemoveRows();
beginInsertRows(parentIndex, row, row);
newEntry->setParent(parent, row);
endInsertRows();
return true;
} catch(...) {
IoUtilities::catchIoFailure();
}
}
}
}
break; break;
case DefaultExpandedRole: }
switch(entry->type()) { try {
case EntryType::Account: ss.write(array.data(), array.size());
return false; Entry *newEntry = Entry::parse(ss);
case EntryType::Node: int row = entry->index();
static_cast<NodeEntry *>(entry)->setExpandedByDefault(value.toBool()); beginRemoveRows(parentIndex, row, row);
emit dataChanged(index, index, QVector<int>() << role); delete entry;
return true; endRemoveRows();
} beginInsertRows(parentIndex, row, row);
break; newEntry->setParent(parent, row);
default: endInsertRows();
; return true;
} catch(...) {
IoUtilities::catchIoFailure();
} }
} }
break;
case DefaultExpandedRole:
switch(entry->type()) {
case EntryType::Account:
return false;
case EntryType::Node:
static_cast<NodeEntry *>(entry)->setExpandedByDefault(value.toBool());
emit dataChanged(index, index, QVector<int>() << role);
return true;
}
break;
default:
;
} }
return false; return false;
} }
@ -388,30 +392,30 @@ bool EntryModel::insertRows(int row, int count, const QModelIndex &parent)
return push(new EntryModelInsertRowsCommand(this, row, count, parent)); return push(new EntryModelInsertRowsCommand(this, row, count, parent));
} }
#endif #endif
if(parent.isValid()) { if(!parent.isValid()) {
if(Entry *parentEntry = static_cast<Entry *>(parent.internalPointer())) { return false;
if(parentEntry->type() == EntryType::Node) {
beginInsertRows(parent, row, row + count - 1);
for(int end = row + count; row < end; ++row) {
Entry *newEntry;
switch(m_insertType) {
case EntryType::Node:
newEntry = new NodeEntry;
break;
case EntryType::Account:
newEntry = new AccountEntry;
break;
default:
return false; // should never be reached, just to suppress compiler warning
}
newEntry->setParent(static_cast<NodeEntry *>(parentEntry), row);
}
endInsertRows();
return true;
}
}
} }
return false; auto *const parentEntry = static_cast<Entry *>(parent.internalPointer());
if(!parentEntry || parentEntry->type() != EntryType::Node) {
return false;
}
beginInsertRows(parent, row, row + count - 1);
for(int end = row + count; row < end; ++row) {
Entry *newEntry;
switch(m_insertType) {
case EntryType::Node:
newEntry = new NodeEntry;
break;
case EntryType::Account:
newEntry = new AccountEntry;
break;
default:
return false; // should never be reached, just to suppress compiler warning
}
newEntry->setParent(static_cast<NodeEntry *>(parentEntry), row);
}
endInsertRows();
return true;
} }
bool EntryModel::removeRows(int row, int count, const QModelIndex &parent) bool EntryModel::removeRows(int row, int count, const QModelIndex &parent)
@ -421,17 +425,17 @@ bool EntryModel::removeRows(int row, int count, const QModelIndex &parent)
return push(new EntryModelRemoveRowsCommand(this, row, count, parent)); return push(new EntryModelRemoveRowsCommand(this, row, count, parent));
} }
#endif #endif
if(parent.isValid() && count > 0) { if(!parent.isValid() || count <= 0) {
if(Entry *parentEntry = static_cast<Entry *>(parent.internalPointer())) { return false;
if(parentEntry->type() == EntryType::Node) {
beginRemoveRows(parent, row, row + count - 1);
static_cast<NodeEntry *>(parentEntry)->deleteChildren(row, row + count);
endRemoveRows();
return true;
}
}
} }
return false; auto *const parentEntry = static_cast<Entry *>(parent.internalPointer());
if(!parentEntry || parentEntry->type() != EntryType::Node) {
return false;
}
beginRemoveRows(parent, row, row + count - 1);
static_cast<NodeEntry *>(parentEntry)->deleteChildren(row, row + count);
endRemoveRows();
return true;
} }
bool EntryModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) bool EntryModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild)
@ -442,41 +446,42 @@ bool EntryModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int co
} }
#endif #endif
// check validation of specified arguments // check validation of specified arguments
if(sourceParent.isValid() && destinationParent.isValid() if(!sourceParent.isValid() || !destinationParent.isValid()
&& sourceRow >= 0 && count > 0 || sourceRow < 0 || count <= 0
&& entry(sourceParent)->type() == EntryType::Node // source and destination parent entries || entry(sourceParent)->type() != EntryType::Node // source and destination parent entries
&& entry(destinationParent)->type() == EntryType::Node) { // need to be node entries || entry(destinationParent)->type() != EntryType::Node) { // need to be node entries
// determine the source parent entry and dest parent entry as node entries return false;
NodeEntry *srcParentEntry = static_cast<NodeEntry *>(sourceParent.internalPointer()); }
NodeEntry *destParentEntry = static_cast<NodeEntry *>(destinationParent.internalPointer()); // determine the source parent entry and dest parent entry as node entries
// source rows must be within the valid range auto *const srcParentEntry = static_cast<NodeEntry *>(sourceParent.internalPointer());
if(static_cast<size_t>(sourceRow + count) <= srcParentEntry->children().size() auto *const destParentEntry = static_cast<NodeEntry *>(destinationParent.internalPointer());
// if source and destination parent are the same the destination child mustn't be in the source range // source rows must be within the valid range
&& (srcParentEntry != destParentEntry || (destinationChild < sourceRow || (sourceRow + count) < destinationChild))) { if(static_cast<size_t>(sourceRow + count) > srcParentEntry->children().size()
// do not move a row to one of its own children! -> check before // if source and destination parent are the same the destination child mustn't be in the source range
for(int index = 0; index < count; ++index) { || !(srcParentEntry != destParentEntry || (destinationChild < sourceRow || (sourceRow + count) < destinationChild))) {
Entry *toMove = srcParentEntry->children().at(sourceRow + index); return false;
if(toMove->type() == EntryType::Node) { }
if(destParentEntry->isIndirectChildOf(static_cast<NodeEntry *>(toMove))) { // do not move a row to one of its own children! -> check before
return false; for(int index = 0; index < count; ++index) {
} Entry *toMove = srcParentEntry->children()[static_cast<size_t>(sourceRow + index)];
} if(toMove->type() == EntryType::Node) {
if(destParentEntry->isIndirectChildOf(static_cast<NodeEntry *>(toMove))) {
return false;
} }
// actually perform the move operation
beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild);
for(int index = 0; index < count; ++index) {
Entry *toMove = srcParentEntry->children().at(sourceRow + index);
if(srcParentEntry == destParentEntry && sourceRow < destinationChild) {
toMove->setParent(destParentEntry, destinationChild + index - 1);
} else {
toMove->setParent(destParentEntry, destinationChild + index);
}
}
endMoveRows();
return true;
} }
} }
return false; // actually perform the move operation
beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild);
for(int index = 0; index < count; ++index) {
Entry *toMove = srcParentEntry->children()[static_cast<size_t>(sourceRow + index)];
if(srcParentEntry == destParentEntry && sourceRow < destinationChild) {
toMove->setParent(destParentEntry, destinationChild + index - 1);
} else {
toMove->setParent(destParentEntry, destinationChild + index);
}
}
endMoveRows();
return true;
} }
QStringList EntryModel::mimeTypes() const QStringList EntryModel::mimeTypes() const
@ -497,16 +502,17 @@ QMimeData *EntryModel::mimeData(const QModelIndexList &indexes) const
QStringList plainTextParts; QStringList plainTextParts;
QByteArray encoded; QByteArray encoded;
QDataStream dataStream(&encoded, QIODevice::WriteOnly); QDataStream dataStream(&encoded, QIODevice::WriteOnly);
foreach(const QModelIndex &index, indexes) { for(const QModelIndex &index : indexes) {
if(index.isValid()) { if(!index.isValid()) {
Entry *entry = static_cast<Entry *>(index.internalPointer()); continue;
list<string> path = entry->path();
dataStream << static_cast<quint32>(path.size());
for(const string &part : path) {
dataStream << QString::fromStdString(part);
}
plainTextParts << QString::fromStdString(entry->label());
} }
const auto *const entry = static_cast<const Entry *>(index.internalPointer());
const auto path(entry->path());
dataStream << static_cast<quint32>(path.size());
for(const string &part : path) {
dataStream << QString::fromStdString(part);
}
plainTextParts << QString::fromStdString(entry->label());
} }
data->setData(types.at(0), encoded); data->setData(types.at(0), encoded);
data->setText(plainTextParts.join(QStringLiteral(", "))); data->setText(plainTextParts.join(QStringLiteral(", ")));
@ -533,7 +539,7 @@ bool EntryModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int
column = 0; column = 0;
} }
// decode and insert // decode and insert
QByteArray encoded = data->data(format); QByteArray encoded(data->data(format));
QDataStream stream(&encoded, QIODevice::ReadOnly); QDataStream stream(&encoded, QIODevice::ReadOnly);
int moved = 0; int moved = 0;
while(!stream.atEnd()) { while(!stream.atEnd()) {
@ -545,12 +551,13 @@ bool EntryModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int
stream >> part; stream >> part;
path.push_back(part.toStdString()); path.push_back(part.toStdString());
} }
if(Entry *entry = m_rootEntry->entryByPath(path, true)) { auto *const entry = m_rootEntry->entryByPath(path, true);
if(NodeEntry *srcParentEntry = entry->parent()) { if(!entry) {
if(moveRows(index(srcParentEntry), entry->index(), 1, parent, row)) { continue;
++moved; }
} auto *const srcParentEntry = entry->parent();
} if(srcParentEntry && moveRows(index(srcParentEntry), entry->index(), 1, parent, row)) {
++moved;
} }
} }
return false; return false;

View File

@ -55,60 +55,62 @@ FieldModel::FieldModel(QUndoStack *undoStack, QObject *parent) :
*/ */
void FieldModel::setAccountEntry(AccountEntry *entry) void FieldModel::setAccountEntry(AccountEntry *entry)
{ {
if(entry != m_accountEntry) { if(entry == m_accountEntry) {
beginResetModel(); return;
if((m_accountEntry = entry)) {
m_fields = &entry->fields();
} else {
m_fields = nullptr;
}
endResetModel();
} }
beginResetModel();
if((m_accountEntry = entry)) {
m_fields = &entry->fields();
} else {
m_fields = nullptr;
}
endResetModel();
} }
QVariant FieldModel::data(const QModelIndex &index, int role) const QVariant FieldModel::data(const QModelIndex &index, int role) const
{ {
if(index.isValid() && m_fields && index.row() >= 0) { if(!index.isValid() || !m_fields || index.row() < 0) {
// return data for existent field return QVariant();
if(static_cast<size_t>(index.row()) < m_fields->size()) { }
switch(role) { // return data for existent field
case Qt::DisplayRole: if(static_cast<size_t>(index.row()) < m_fields->size()) {
case Qt::EditRole: switch(role) {
switch(index.column()) { case Qt::DisplayRole:
case 0: case Qt::EditRole:
return QString::fromStdString(m_fields->at(index.row()).name()); switch(index.column()) {
case 1: case 0:
return (m_passwordVisibility == PasswordVisibility::Always return QString::fromStdString((*m_fields)[static_cast<size_t>(index.row())].name());
|| role == Qt::EditRole case 1:
|| m_fields->at(index.row()).type() != FieldType::Password) return (m_passwordVisibility == PasswordVisibility::Always
? QString::fromStdString(m_fields->at(index.row()).value()) || role == Qt::EditRole
: QString(m_fields->at(index.row()).value().size(), QChar(0x2022)); || (*m_fields)[static_cast<size_t>(index.row())].type() != FieldType::Password)
default: ? QString::fromStdString((*m_fields)[static_cast<size_t>(index.row())].value())
; : QString((*m_fields)[static_cast<size_t>(index.row())].value().size(), QChar(0x2022));
}
break;
case FieldTypeRole:
return static_cast<int>(m_fields->at(index.row()).type());
default: default:
; ;
} }
// return data for empty field at the end which enables the user to append fields break;
} else if(static_cast<size_t>(index.row()) == m_fields->size()) { case FieldTypeRole:
switch(role) { return static_cast<int>((*m_fields)[static_cast<size_t>(index.row())].type());
case Qt::DisplayRole: default:
case Qt::EditRole: ;
switch(index.column()) { }
case 0: // return data for empty field at the end which enables the user to append fields
return QString(); } else if(static_cast<size_t>(index.row()) == m_fields->size()) {
case 1: switch(role) {
return QString(); case Qt::DisplayRole:
default: case Qt::EditRole:
; switch(index.column()) {
} case 0:
break; return QString();
case 1:
return QString();
default: default:
; ;
} }
break;
default:
;
} }
} }
return QVariant(); return QVariant();
@ -116,14 +118,16 @@ QVariant FieldModel::data(const QModelIndex &index, int role) const
QMap<int, QVariant> FieldModel::itemData(const QModelIndex &index) const QMap<int, QVariant> FieldModel::itemData(const QModelIndex &index) const
{ {
static int roles[] = {Qt::EditRole, FieldTypeRole}; static const auto roleMap = [this, index] {
QMap<int, QVariant> roleMap; QMap<int, QVariant> roleMap;
for(int role : roles) { for(const auto role : initializer_list<int>{Qt::EditRole, FieldTypeRole}) {
QVariant variantData = data(index, role); const auto variantData(data(index, role));
if (variantData.isValid()) { if (variantData.isValid()) {
roleMap.insert(role, variantData); roleMap.insert(role, variantData);
}
} }
} return roleMap;
}();
return roleMap; return roleMap;
} }
@ -134,86 +138,86 @@ bool FieldModel::setData(const QModelIndex &index, const QVariant &value, int ro
return push(new FieldModelSetValueCommand(this, index, value, role)); return push(new FieldModelSetValueCommand(this, index, value, role));
} }
#endif #endif
if(!index.isValid() || !m_fields || index.row() < 0) {
return false;
}
QVector<int> roles; QVector<int> roles;
if(index.isValid() && m_fields && index.row() >= 0) { if(static_cast<size_t>(index.row()) < m_fields->size()) {
// set data for existing field // set data for existing field
if(static_cast<size_t>(index.row()) < m_fields->size()) { switch(role) {
switch(role) { case Qt::EditRole:
case Qt::EditRole: switch(index.column()) {
switch(index.column()) { case 0:
case 0: m_fields->at(index.row()).setName(value.toString().toStdString());
m_fields->at(index.row()).setName(value.toString().toStdString()); roles << role;
roles << role;
break;
case 1:
m_fields->at(index.row()).setValue(value.toString().toStdString());
roles << role;
break;
default:
;
}
break; break;
case FieldTypeRole: { case 1:
bool ok; m_fields->at(index.row()).setValue(value.toString().toStdString());
int fieldType = value.toInt(&ok); roles << role;
if(ok && Field::isValidType(fieldType)) {
roles << role;
m_fields->at(index.row()).setType(static_cast<FieldType>(fieldType));
}
break;
} default:
;
}
// remove last field if empty, showing an empty field at the end to enabled appending new rows is provided by the data method
if(!roles.isEmpty() && static_cast<size_t>(index.row()) == m_fields->size() - 1 && m_fields->at(index.row()).isEmpty()) {
beginRemoveRows(index.parent(), index.row(), index.row());
m_fields->pop_back();
endRemoveRows();
}
// set data for a new field emplaced at the end of the field list
} else if(static_cast<size_t>(index.row()) == m_fields->size() && !value.toString().isEmpty()) {
switch(role) {
case Qt::DisplayRole:
case Qt::EditRole:
switch(index.column()) {
case 0:
beginInsertRows(index.parent(), rowCount(), rowCount());
m_fields->emplace_back(m_accountEntry);
m_fields->back().setName(value.toString().toStdString());
endInsertRows();
roles << role;
break;
case 1:
beginInsertRows(index.parent(), rowCount(), rowCount());
m_fields->emplace_back(m_accountEntry);
m_fields->back().setValue(value.toString().toStdString());
endInsertRows();
roles << role;
break;
default:
;
}
break; break;
default: default:
; ;
} }
break;
case FieldTypeRole: {
bool ok;
int fieldType = value.toInt(&ok);
if(ok && Field::isValidType(fieldType)) {
roles << role;
m_fields->at(index.row()).setType(static_cast<FieldType>(fieldType));
}
break;
} default:
;
}
// remove last field if empty, showing an empty field at the end to enabled appending new rows is provided by the data method
if(!roles.isEmpty() && static_cast<size_t>(index.row()) == m_fields->size() - 1 && m_fields->at(index.row()).isEmpty()) {
beginRemoveRows(index.parent(), index.row(), index.row());
m_fields->pop_back();
endRemoveRows();
}
} else if(static_cast<size_t>(index.row()) == m_fields->size() && !value.toString().isEmpty()) {
// set data for a new field emplaced at the end of the field list
switch(role) {
case Qt::DisplayRole:
case Qt::EditRole:
switch(index.column()) {
case 0:
beginInsertRows(index.parent(), rowCount(), rowCount());
m_fields->emplace_back(m_accountEntry);
m_fields->back().setName(value.toString().toStdString());
endInsertRows();
roles << role;
break;
case 1:
beginInsertRows(index.parent(), rowCount(), rowCount());
m_fields->emplace_back(m_accountEntry);
m_fields->back().setValue(value.toString().toStdString());
endInsertRows();
roles << role;
break;
default:
;
}
break;
default:
;
} }
} }
// return false if nothing could be changed // return false if nothing could be changed
if(roles.isEmpty()) { if(roles.isEmpty()) {
return false; return false;
} else { }
// some roles affect other roles // some roles affect other roles
switch(role) { switch(role) {
case Qt::EditRole: case Qt::EditRole:
roles << Qt::DisplayRole; roles << Qt::DisplayRole;
break; break;
case FieldTypeRole: case FieldTypeRole:
roles << Qt::DisplayRole << Qt::EditRole; roles << Qt::DisplayRole << Qt::EditRole;
break; break;
default: default:
; ;
}
} }
// emit data changed signal on sucess // emit data changed signal on sucess
emit dataChanged(index, index, roles); emit dataChanged(index, index, roles);
@ -267,13 +271,13 @@ bool FieldModel::insertRows(int row, int count, const QModelIndex &parent)
return push(new FieldModelInsertRowsCommand(this, row, count)); return push(new FieldModelInsertRowsCommand(this, row, count));
} }
#endif #endif
if(!parent.isValid() && row >= 0 && count > 0 && static_cast<size_t>(row) <= m_fields->size()) { if(parent.isValid() || row < 0 || count <= 0 || static_cast<size_t>(row + count) > m_fields->size()) {
beginInsertRows(parent, row, row + count - 1); return false;
m_fields->insert(m_fields->begin() + row, count, Field(m_accountEntry));
endInsertRows();
return true;
} }
return false; beginInsertRows(parent, row, row + count - 1);
m_fields->insert(m_fields->begin() + row, static_cast<size_t>(count), Field(m_accountEntry));
endInsertRows();
return true;
} }
bool FieldModel::removeRows(int row, int count, const QModelIndex &parent) bool FieldModel::removeRows(int row, int count, const QModelIndex &parent)
@ -283,21 +287,18 @@ bool FieldModel::removeRows(int row, int count, const QModelIndex &parent)
return push(new FieldModelRemoveRowsCommand(this, row, count)); return push(new FieldModelRemoveRowsCommand(this, row, count));
} }
#endif #endif
if(!parent.isValid() && row >= 0 && count > 0 && static_cast<size_t>(row + count) <= m_fields->size()) { if(parent.isValid() || row < 0 || count <= 0 || static_cast<size_t>(row + count) > m_fields->size()) {
beginRemoveRows(parent, row, row + count - 1); return false;
m_fields->erase(m_fields->begin() + row, m_fields->begin() + row + count);
endRemoveRows();
return true;
} }
return false; beginRemoveRows(parent, row, row + count - 1);
m_fields->erase(m_fields->begin() + row, m_fields->begin() + row + count);
endRemoveRows();
} }
bool FieldModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) bool FieldModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{ {
if(!QAbstractTableModel::dropMimeData(data, action, row, column, parent)) { if(!QAbstractTableModel::dropMimeData(data, action, row, column, parent) && data->hasText()) {
if(data->hasText()) { return setData(parent, data->text(), Qt::EditRole);
return setData(parent, data->text(), Qt::EditRole);
}
} }
return false; return false;
} }
@ -310,13 +311,14 @@ QStringList FieldModel::mimeTypes() const
QMimeData *FieldModel::mimeData(const QModelIndexList &indexes) const QMimeData *FieldModel::mimeData(const QModelIndexList &indexes) const
{ {
QMimeData *data = QAbstractTableModel::mimeData(indexes); QMimeData *data = QAbstractTableModel::mimeData(indexes);
if(!indexes.isEmpty()) { if(indexes.isEmpty()) {
QStringList result; return data;
foreach(const QModelIndex &index, indexes) {
result << index.data(Qt::EditRole).toString();
}
data->setText(result.join(QChar('\n')));
} }
QStringList result;
for(const QModelIndex &index : indexes) {
result << index.data(Qt::EditRole).toString();
}
data->setText(result.join(QChar('\n')));
return data; return data;
} }
@ -328,7 +330,7 @@ QMimeData *FieldModel::mimeData(const QModelIndexList &indexes) const
const Field *FieldModel::field(size_t row) const const Field *FieldModel::field(size_t row) const
{ {
if(m_fields && row < m_fields->size()) { if(m_fields && row < m_fields->size()) {
return &m_fields->at(row); return &(*m_fields)[row];
} }
return nullptr; return nullptr;
} }

View File

@ -30,10 +30,12 @@ inline QString ApplicationPaths::path(QStandardPaths::StandardLocation location)
{ {
QString path = QStandardPaths::standardLocations(location).value(0); QString path = QStandardPaths::standardLocations(location).value(0);
QDir dir(path); QDir dir(path);
if (!dir.exists()) if (!dir.exists()) {
dir.mkpath(path); dir.mkpath(path);
if (!path.isEmpty() && !path.endsWith("/")) }
if (!path.isEmpty() && !path.endsWith("/")) {
path += "/"; path += "/";
}
return path; return path;
} }
} // namespace QtGui } // namespace QtGui