wip set/delete items

This commit is contained in:
mappu 2017-05-21 17:44:07 +12:00
parent 14e7ebb59c
commit 37f9307db1
6 changed files with 197 additions and 88 deletions

42
main.go
View File

@ -148,6 +148,48 @@ func Bolt_DeleteBucket(b_ref ObjectReference, browse []string, delBucket string)
return err2triple(err) return err2triple(err)
} }
//export Bolt_SetItem
func Bolt_SetItem(b_ref ObjectReference, browse []string, key, val string) (int64, *C.char, int) {
if len(browse) == 0 {
return err2triple(errors.New("Can't create top-level items"))
}
err := withBoltDBReference(b_ref, func(db *bolt.DB) error {
return db.Update(func(tx *bolt.Tx) error {
bucket, err := walkBuckets(tx, browse)
if err != nil {
return err
}
return bucket.Put([]byte(key), []byte(val))
})
})
return err2triple(err)
}
//export Bolt_DeleteItem
func Bolt_DeleteItem(b_ref ObjectReference, browse []string, key string) (int64, *C.char, int) {
if len(browse) == 0 {
return err2triple(errors.New("Can't create top-level items"))
}
err := withBoltDBReference(b_ref, func(db *bolt.DB) error {
return db.Update(func(tx *bolt.Tx) error {
bucket, err := walkBuckets(tx, browse)
if err != nil {
return err
}
return bucket.Delete([]byte(key))
})
})
return err2triple(err)
}
type CallResponse struct { type CallResponse struct {
s string s string
e error e error

View File

@ -29,18 +29,13 @@ static const int ERROR_AND_KEEP_CALLING = 101;
static const int FINISHED_OK = 102; static const int FINISHED_OK = 102;
static const int REAL_MESSAGE = 103; static const int REAL_MESSAGE = 103;
bool BoltDB::addBucket(QStringList bucketPath, QByteArray bucketName, QString& errorOut) static bool handleTriple(int r0, char* r1, int64_t r2, QString& errorOut) {
{ if (r0 == ERROR_AND_STOP_CALLING) {
GoSliceManagedWrapper browse(&bucketPath); errorOut = QString::fromUtf8(r1, r2);
GoString bucketNameGS = Interop::toGoString_WeakRef(&bucketName); free(r1);
auto resp = ::Bolt_CreateBucket(this->gmsDbRef, browse.slice, bucketNameGS);
if (resp.r0 == ERROR_AND_STOP_CALLING) {
errorOut = QString::fromUtf8(resp.r1, resp.r2);
free(resp.r1);
return false; return false;
} else if (resp.r0 == FINISHED_OK) { } else if (r0 == FINISHED_OK) {
return true; return true;
} else { } else {
@ -50,27 +45,44 @@ bool BoltDB::addBucket(QStringList bucketPath, QByteArray bucketName, QString& e
} }
} }
bool BoltDB::addBucket(QStringList bucketPath, QByteArray bucketName, QString& errorOut)
{
GoSliceManagedWrapper browse(&bucketPath);
GoString bucketNameGS = Interop::toGoString_WeakRef(&bucketName);
auto resp = ::Bolt_CreateBucket(this->gmsDbRef, browse.slice, bucketNameGS);
return handleTriple(resp.r0, resp.r1, resp.r2, errorOut);
}
bool BoltDB::deleteBucket(QStringList bucketPath, QByteArray bucketName, QString& errorOut) bool BoltDB::deleteBucket(QStringList bucketPath, QByteArray bucketName, QString& errorOut)
{ {
GoSliceManagedWrapper browse(&bucketPath); GoSliceManagedWrapper browse(&bucketPath);
GoString bucketNameGS = Interop::toGoString_WeakRef(&bucketName); GoString bucketNameGS = Interop::toGoString_WeakRef(&bucketName);
auto resp = ::Bolt_DeleteBucket(this->gmsDbRef, browse.slice, bucketNameGS); auto resp = ::Bolt_DeleteBucket(this->gmsDbRef, browse.slice, bucketNameGS);
if (resp.r0 == ERROR_AND_STOP_CALLING) { return handleTriple(resp.r0, resp.r1, resp.r2, errorOut);
errorOut = QString::fromUtf8(resp.r1, resp.r2);
free(resp.r1);
return false;
} else if (resp.r0 == FINISHED_OK) {
return true;
} else {
// ?? unreachable
return false;
}
} }
bool BoltDB::setItem(QStringList bucketPath, QByteArray keyName, QByteArray value, QString& errorOut)
{
GoSliceManagedWrapper browse(&bucketPath);
GoString keyNameGS = Interop::toGoString_WeakRef(&keyName);
GoString valueGS = Interop::toGoString_WeakRef(&value);
auto resp = ::Bolt_SetItem(this->gmsDbRef, browse.slice, keyNameGS, valueGS);
return handleTriple(resp.r0, resp.r1, resp.r2, errorOut);
}
bool BoltDB::deleteItem(QStringList bucketPath, QByteArray keyName, QString& errorOut)
{
GoSliceManagedWrapper browse(&bucketPath);
GoString keyNameGS = Interop::toGoString_WeakRef(&keyName);
auto resp = ::Bolt_DeleteItem(this->gmsDbRef, browse.slice, keyNameGS);
return handleTriple(resp.r0, resp.r1, resp.r2, errorOut);
}
bool BoltDB::listBucketsAtRoot(QString& errorOut, NameReciever cb) bool BoltDB::listBucketsAtRoot(QString& errorOut, NameReciever cb)
{ {
auto listJob = ::Bolt_ListBucketsAtRoot(this->gmsDbRef); auto listJob = ::Bolt_ListBucketsAtRoot(this->gmsDbRef);

View File

@ -24,6 +24,10 @@ public:
bool deleteBucket(QStringList bucketPath, QByteArray bucketName, QString& errorOut); bool deleteBucket(QStringList bucketPath, QByteArray bucketName, QString& errorOut);
bool setItem(QStringList bucketPath, QByteArray keyName, QByteArray value, QString& errorOut);
bool deleteItem(QStringList bucketPath, QByteArray keyName, QString& errorOut);
bool listKeys(QStringList bucketPath, QString& errorOut, std::function<void(QByteArray, int64_t)> cb); bool listKeys(QStringList bucketPath, QString& errorOut, std::function<void(QByteArray, int64_t)> cb);
bool getData(QStringList bucketPath, QByteArray key, std::function<void(QByteArray)> onSuccess, std::function<void(QString)> onError); bool getData(QStringList bucketPath, QByteArray key, std::function<void(QByteArray)> onSuccess, std::function<void(QString)> onError);

View File

@ -235,52 +235,56 @@ void MainWindow::on_bucketTree_currentItemChanged(QTreeWidgetItem *current, QTre
); );
// Load the data tab // Load the data tab
ui->bucketData->clear(); refreshData(bdb, browse);
QString err;
bool ok = bdb->listKeys(browse, err, [=](QByteArray name, int64_t dataLen) {
auto *itm = new QTreeWidgetItem();
itm->setText(0, QString::fromUtf8(name));
itm->setText(1, QString("%1").arg(dataLen));
ui->bucketData->addTopLevelItem(itm);
});
if (! ok) {
QMessageBox qmb;
qmb.setText(tr("Error listing bucket content: %1").arg(err));
qmb.exec();
}
ui->bucketData->resizeColumnToContents(0);
// Clean up foreign areas // Clean up foreign areas
ui->databasePropertiesArea->clear(); ui->databasePropertiesArea->clear();
} }
} }
void MainWindow::refreshData(BoltDB *bdb, QStringList browse)
{
// Load the data tab
ui->bucketData->clear();
QString err;
bool ok = bdb->listKeys(browse, err, [=](QByteArray name, int64_t dataLen) {
auto *itm = new QTreeWidgetItem();
itm->setText(0, QString::fromUtf8(name));
itm->setText(1, QString("%1").arg(dataLen));
ui->bucketData->addTopLevelItem(itm);
});
if (! ok) {
QMessageBox qmb;
qmb.setText(tr("Error listing bucket content: %1").arg(err));
qmb.exec();
}
ui->bucketData->resizeColumnToContents(0);
on_bucketData_itemSelectionChanged();
}
void MainWindow::on_actionClear_selection_triggered() void MainWindow::on_actionClear_selection_triggered()
{ {
ui->bucketTree->setCurrentItem(nullptr); ui->bucketTree->setCurrentItem(nullptr);
} }
#define GET_ITM_TOP_BROWSE_BDB \
QTreeWidgetItem* itm = lastContextSelection; \
if (itm == nullptr) { \
return; \
} \
QTreeWidgetItem* top = itm; \
QStringList browse; \
while(top->parent() != nullptr) { \
browse.push_front(top->text(0)); \
top = top->parent(); \
} \
auto *bdb = GET_BDB(top);
void MainWindow::on_bucketData_doubleClicked(const QModelIndex &index) void MainWindow::on_bucketData_doubleClicked(const QModelIndex &index)
{ {
auto *itm = ui->bucketTree->currentItem(); GET_ITM_TOP_BROWSE_BDB;
if (itm == nullptr) {
return;
}
// Get browse path
QTreeWidgetItem* top = itm;
QStringList browse;
while(top->parent() != nullptr) {
browse.push_front(top->text(0));
top = top->parent();
}
// Get BDB
auto *bdb = GET_BDB(top);
// Get item key // Get item key
@ -310,21 +314,7 @@ void MainWindow::on_bucketData_doubleClicked(const QModelIndex &index)
void MainWindow::on_actionAdd_bucket_triggered() void MainWindow::on_actionAdd_bucket_triggered()
{ {
QTreeWidgetItem* itm = lastContextSelection; GET_ITM_TOP_BROWSE_BDB;
if (itm == nullptr) {
return;
}
QTreeWidgetItem* top = itm;
QStringList browse;
while(top->parent() != nullptr) {
browse.push_front(top->text(0));
top = top->parent();
}
// Get BDB
auto *bdb = GET_BDB(top);
// Prompt for bucket name // Prompt for bucket name
@ -349,21 +339,7 @@ void MainWindow::on_actionAdd_bucket_triggered()
void MainWindow::on_actionDelete_bucket_triggered() void MainWindow::on_actionDelete_bucket_triggered()
{ {
QTreeWidgetItem* itm = lastContextSelection; GET_ITM_TOP_BROWSE_BDB;
if (itm == nullptr) {
return;
}
QTreeWidgetItem* top = itm;
QStringList browse;
while(top->parent() != nullptr) {
browse.push_front(top->text(0));
top = top->parent();
}
// Get BDB
auto *bdb = GET_BDB(top);
// Prompt for confirmation // Prompt for confirmation
QString bucketToDelete = itm->text(0); QString bucketToDelete = itm->text(0);
@ -388,3 +364,40 @@ void MainWindow::on_actionDelete_bucket_triggered()
ui->bucketTree->expandItem(itm->parent()); ui->bucketTree->expandItem(itm->parent());
} }
void MainWindow::on_AddDataButton_clicked()
{
}
void MainWindow::on_DeleteDataButton_clicked()
{
GET_ITM_TOP_BROWSE_BDB;
auto selection = ui->bucketData->selectedItems();
if (selection.length() == 0) {
return; // nothing to do
}
// Prompt for confirmation
if (QMessageBox::question(this, tr("Delete items"), tr("Are you sure you want to remove %1 item(s)?").arg(selection.length()), QMessageBox::Yes, QMessageBox::Cancel) != QMessageBox::Yes) {
return;
}
QString err;
for (int i = selection.length(); i-->0;) {
if (! bdb->deleteItem(browse, selection[i]->text(0).toUtf8(), err)) {
QMessageBox qmb;
qmb.setText(tr("Error removing item: %1").arg(err));
qmb.exec();
}
}
refreshData(bdb, browse);
}
void MainWindow::on_bucketData_itemSelectionChanged()
{
ui->DeleteDataButton->setEnabled( (ui->bucketData->selectedItems().size() > 0) );
}

View File

@ -1,6 +1,7 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#include "boltdb.h"
#include <QMainWindow> #include <QMainWindow>
#include <QMenu> #include <QMenu>
#include <QTreeWidgetItem> #include <QTreeWidgetItem>
@ -44,9 +45,16 @@ private slots:
void on_actionDelete_bucket_triggered(); void on_actionDelete_bucket_triggered();
void on_AddDataButton_clicked();
void on_DeleteDataButton_clicked();
void on_bucketData_itemSelectionChanged();
protected: protected:
void openDatabase(QString file); void openDatabase(QString file);
void refreshBucketTree(QTreeWidgetItem* top); void refreshBucketTree(QTreeWidgetItem* top);
void refreshData(BoltDB *bdb, QStringList browse);
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;

View File

@ -128,7 +128,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QTabWidget" name="bucketTabWidget"> <widget class="QTabWidget" name="bucketTabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="bucketPropertiesTab"> <widget class="QWidget" name="bucketPropertiesTab">
<attribute name="title"> <attribute name="title">
@ -176,8 +176,11 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>3</number> <number>3</number>
</property> </property>
<item row="0" column="0"> <item row="0" column="0" colspan="3">
<widget class="QTreeWidget" name="bucketData"> <widget class="QTreeWidget" name="bucketData">
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="indentation"> <property name="indentation">
<number>0</number> <number>0</number>
</property> </property>
@ -202,6 +205,33 @@
</column> </column>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QPushButton" name="AddDataButton">
<property name="text">
<string>Add...</string>
</property>
</widget>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="DeleteDataButton">
<property name="text">
<string>Delete...</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>