2017-05-16 07:34:54 +00:00
# include "mainwindow.h"
# include "ui_mainwindow.h"
2017-05-21 04:44:44 +00:00
# include "itemwindow.h"
2017-05-20 02:57:51 +00:00
# include "boltdb.h"
2017-05-16 07:34:54 +00:00
# include <QFileDialog>
# include <QMessageBox>
2017-05-21 03:49:47 +00:00
# include <QJsonDocument>
2017-05-21 05:08:15 +00:00
# include <QInputDialog>
2017-05-16 07:34:54 +00:00
MainWindow : : MainWindow ( QWidget * parent ) :
QMainWindow ( parent ) ,
ui ( new Ui : : MainWindow )
{
ui - > setupUi ( this ) ;
2017-05-20 23:47:16 +00:00
on_bucketTree_currentItemChanged ( nullptr , nullptr ) ;
databaseContext = new QMenu ( ) ;
databaseContext - > addAction ( ui - > actionRefresh_buckets ) ;
2017-05-21 05:08:15 +00:00
databaseContext - > addAction ( ui - > actionAdd_bucket ) ;
databaseContext - > addSeparator ( ) ;
2017-05-20 23:47:16 +00:00
databaseContext - > addAction ( ui - > actionDisconnect ) ;
bucketContext = new QMenu ( ) ;
2017-05-21 01:49:41 +00:00
bucketContext - > addAction ( ui - > actionRefresh_buckets ) ;
2017-05-21 05:08:15 +00:00
bucketContext - > addAction ( ui - > actionAdd_bucket ) ;
bucketContext - > addSeparator ( ) ;
2017-05-20 23:47:16 +00:00
bucketContext - > addAction ( ui - > actionDelete_bucket ) ;
2017-05-16 07:34:54 +00:00
}
MainWindow : : ~ MainWindow ( )
{
delete ui ;
}
2017-05-20 23:47:16 +00:00
static const int BdbPointerRole = Qt : : UserRole + 1 ;
# define SET_BDB(top, bdb) top->setData(0, BdbPointerRole, QVariant::fromValue<void*>(static_cast<void*>(bdb)))
# define GET_BDB(top) static_cast<BoltDB*>( top->data(0, BdbPointerRole).value<void*>() )
2017-05-21 04:50:17 +00:00
void MainWindow : : on_actionNew_database_triggered ( )
{
QString file = QFileDialog : : getSaveFileName ( this , tr ( " Save new bolt database as... " ) ) ;
if ( file . length ( ) ) {
openDatabase ( file ) ;
}
}
2017-05-16 07:34:54 +00:00
void MainWindow : : on_actionOpen_database_triggered ( )
{
QString file = QFileDialog : : getOpenFileName ( this , tr ( " Select bolt database... " ) ) ;
2017-05-21 04:50:17 +00:00
if ( file . length ( ) ) {
openDatabase ( file ) ;
2017-05-16 07:34:54 +00:00
}
2017-05-21 04:50:17 +00:00
}
2017-05-16 07:34:54 +00:00
2017-05-21 04:50:17 +00:00
void MainWindow : : openDatabase ( QString file )
{
2017-05-20 02:57:51 +00:00
// Open
QString error ;
auto * bdb = BoltDB : : createFrom ( file , error ) ;
if ( bdb = = nullptr ) {
2017-05-16 07:34:54 +00:00
QMessageBox qmb ;
2017-05-20 05:28:27 +00:00
qmb . setText ( tr ( " Error opening database: %1 " ) . arg ( error ) ) ;
2017-05-16 07:34:54 +00:00
qmb . exec ( ) ;
return ;
}
2017-05-20 03:47:05 +00:00
QTreeWidgetItem * top = new QTreeWidgetItem ( ) ;
2017-05-20 23:47:16 +00:00
top - > setText ( 0 , QFileInfo ( file ) . fileName ( ) ) ;
2017-05-20 03:47:05 +00:00
top - > setIcon ( 0 , QIcon ( " :/rsrc/database.png " ) ) ;
2017-05-20 23:47:16 +00:00
SET_BDB ( top , bdb ) ;
2017-05-20 03:47:05 +00:00
ui - > bucketTree - > addTopLevelItem ( top ) ;
2017-05-20 23:47:16 +00:00
refreshBucketTree ( top ) ;
2017-05-21 01:31:28 +00:00
ui - > bucketTree - > setCurrentItem ( top ) ;
2017-05-21 04:44:44 +00:00
ui - > bucketTree - > expandItem ( top ) ;
2017-05-20 23:47:16 +00:00
}
2017-05-21 01:31:28 +00:00
void MainWindow : : refreshBucketTree ( QTreeWidgetItem * itm )
2017-05-20 23:47:16 +00:00
{
2017-05-21 01:31:28 +00:00
QTreeWidgetItem * top = itm ;
QStringList browsePath ;
while ( top - > parent ( ) ! = nullptr ) {
browsePath . push_front ( top - > text ( 0 ) ) ;
top = top - > parent ( ) ;
}
2017-05-20 23:47:16 +00:00
2017-05-21 01:31:28 +00:00
// Remove existing children
for ( int i = itm - > childCount ( ) ; i - - > 0 ; ) {
delete itm - > takeChild ( i ) ;
}
2017-05-21 01:49:36 +00:00
2017-05-21 01:31:28 +00:00
auto * bdb = GET_BDB ( top ) ;
2017-05-20 23:47:16 +00:00
QString error ;
2017-05-21 01:31:28 +00:00
bool ok = bdb - > listBuckets (
browsePath ,
error ,
[ = ] ( QByteArray qba ) {
QTreeWidgetItem * child = new QTreeWidgetItem ( ) ;
child - > setText ( 0 , QString : : fromUtf8 ( qba ) ) ;
child - > setIcon ( 0 , QIcon ( " :/rsrc/table.png " ) ) ;
itm - > addChild ( child ) ;
refreshBucketTree ( child ) ;
}
) ;
2017-05-20 05:28:27 +00:00
if ( ! ok ) {
QMessageBox qmb ;
qmb . setText ( tr ( " Error listing buckets: %1 " ) . arg ( error ) ) ;
qmb . exec ( ) ;
// (continue)
}
2017-05-16 07:34:54 +00:00
}
2017-05-20 03:20:30 +00:00
void MainWindow : : on_actionExit_triggered ( )
{
close ( ) ;
}
void MainWindow : : on_actionAbout_Qt_triggered ( )
{
QApplication : : aboutQt ( ) ;
}
void MainWindow : : on_actionAbout_qbolt_triggered ( )
{
QMessageBox : : about (
this ,
QApplication : : applicationDisplayName ( ) ,
" <b>QBolt</b><br>Graphical interface for managing Bolt databases<br><br> "
" - <a href='https://github.com/boltdb/bolt'>About BoltDB</a><br> "
" - <a href='http://www.famfamfam.com/lab/icons/silk/'>FamFamFam "Silk" icon set</a><br> "
" - <a href='https://code.ivysaur.me/qbolt'>QBolt homepage</a><br> "
) ;
}
2017-05-20 23:47:16 +00:00
void MainWindow : : on_actionDisconnect_triggered ( )
{
QTreeWidgetItem * top = lastContextSelection ;
if ( top - > parent ( ) ) {
return ; // somehow we didn't select a top-level item
}
auto * bdb = GET_BDB ( top ) ;
// Remove UI
ui - > bucketTree - > clearSelection ( ) ;
delete top ;
// Disconnect from DB
delete bdb ;
}
void MainWindow : : on_bucketTree_customContextMenuRequested ( const QPoint & pos )
{
auto * itm = ui - > bucketTree - > itemAt ( pos ) ;
if ( itm = = nullptr ) {
return ;
}
lastContextSelection = itm ;
if ( itm - > parent ( ) ! = nullptr ) {
// Child item, show the bucket menu
bucketContext - > popup ( ui - > bucketTree - > mapToGlobal ( pos ) ) ;
} else {
// Top-level item, show the database menu
databaseContext - > popup ( ui - > bucketTree - > mapToGlobal ( pos ) ) ;
}
}
void MainWindow : : on_actionRefresh_buckets_triggered ( )
{
2017-05-21 01:49:41 +00:00
refreshBucketTree ( lastContextSelection ) ;
2017-05-20 23:47:16 +00:00
}
void MainWindow : : on_bucketTree_currentItemChanged ( QTreeWidgetItem * current , QTreeWidgetItem * previous )
{
Q_UNUSED ( previous ) ;
if ( current = = nullptr ) {
2017-05-21 00:39:55 +00:00
ui - > stackedWidget - > setVisible ( false ) ;
2017-05-20 23:47:16 +00:00
return ;
}
2017-05-21 00:39:55 +00:00
ui - > stackedWidget - > setVisible ( true ) ;
2017-05-20 23:59:38 +00:00
if ( current - > parent ( ) = = nullptr ) {
// Selected a database
2017-05-21 00:39:55 +00:00
ui - > stackedWidget - > setCurrentWidget ( ui - > databasePage ) ;
2017-05-21 01:47:46 +00:00
ui - > databasePropertiesArea - > clear ( ) ;
2017-05-21 00:39:55 +00:00
2017-05-20 23:59:38 +00:00
auto * bdb = GET_BDB ( current ) ;
2017-05-21 00:39:55 +00:00
bdb - > getStatsJSON (
2017-05-21 03:49:47 +00:00
[ = ] ( QByteArray j ) {
auto doc = QJsonDocument : : fromJson ( j ) ;
ui - > databasePropertiesArea - > setPlainText ( QString : : fromUtf8 ( doc . toJson ( QJsonDocument : : Indented ) ) ) ;
2017-05-21 00:39:55 +00:00
} ,
[ = ] ( QString error ) {
2017-05-21 01:47:46 +00:00
ui - > databasePropertiesArea - > setPlainText ( tr ( " Error retrieving database statistics: %1 " ) . arg ( error ) ) ;
2017-05-21 00:39:55 +00:00
}
) ;
2017-05-20 23:59:38 +00:00
2017-05-21 04:15:49 +00:00
// Clean up foreign areas
ui - > bucketPropertiesArea - > clear ( ) ;
ui - > bucketData - > clear ( ) ;
2017-05-20 23:59:38 +00:00
} else {
// Selected a bucket
2017-05-21 00:39:55 +00:00
ui - > stackedWidget - > setCurrentWidget ( ui - > bucketPage ) ;
2017-05-21 01:47:46 +00:00
ui - > bucketPropertiesArea - > clear ( ) ;
2017-05-21 00:39:55 +00:00
QStringList browse ;
QTreeWidgetItem * top = current ;
while ( top - > parent ( ) ! = nullptr ) {
browse . push_front ( top - > text ( 0 ) ) ;
top = top - > parent ( ) ;
}
auto * bdb = GET_BDB ( top ) ;
bdb - > getBucketStatsJSON (
browse ,
2017-05-21 03:49:47 +00:00
[ = ] ( QByteArray j ) {
auto doc = QJsonDocument : : fromJson ( j ) ;
ui - > bucketPropertiesArea - > setPlainText ( QString : : fromUtf8 ( doc . toJson ( QJsonDocument : : Indented ) ) ) ;
2017-05-21 00:39:55 +00:00
} ,
[ = ] ( QString error ) {
2017-05-21 01:47:46 +00:00
ui - > bucketPropertiesArea - > setPlainText ( tr ( " Error retrieving bucket statistics: %1 " ) . arg ( error ) ) ;
2017-05-21 00:39:55 +00:00
}
) ;
2017-05-20 23:59:38 +00:00
// Load the data tab
2017-05-21 05:44:07 +00:00
refreshData ( bdb , browse ) ;
2017-05-21 04:44:44 +00:00
2017-05-21 04:15:49 +00:00
// Clean up foreign areas
ui - > databasePropertiesArea - > clear ( ) ;
2017-05-20 23:59:38 +00:00
}
2017-05-20 23:47:16 +00:00
}
2017-05-21 05:44:07 +00:00
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 ( ) ;
}
2017-05-20 23:47:16 +00:00
void MainWindow : : on_actionClear_selection_triggered ( )
{
ui - > bucketTree - > setCurrentItem ( nullptr ) ;
}
2017-05-21 04:44:44 +00:00
2017-05-21 05:44:07 +00:00
# define GET_ITM_TOP_BROWSE_BDB \
2017-05-21 05:53:40 +00:00
QTreeWidgetItem * itm = ui - > bucketTree - > currentItem ( ) ; \
2017-05-21 05:44:07 +00:00
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 ) ;
2017-05-21 04:44:44 +00:00
void MainWindow : : on_bucketData_doubleClicked ( const QModelIndex & index )
{
2017-05-21 05:44:07 +00:00
GET_ITM_TOP_BROWSE_BDB ;
2017-05-21 04:44:44 +00:00
// Get item key
auto model = index . model ( ) ;
QString key = model - > data ( model - > index ( index . row ( ) , 0 ) , 0 ) . toString ( ) ;
// DB lookup
bdb - > getData (
browse ,
key . toUtf8 ( ) ,
[ = ] ( QByteArray content ) {
auto iw = new ItemWindow ( ) ;
iw - > ContentArea ( ) - > setPlainText ( QString : : fromUtf8 ( content ) ) ;
iw - > setWindowTitle ( key ) ;
2017-05-21 05:53:40 +00:00
connect ( iw , & ItemWindow : : finished , iw , [ = ] ( int exitCode ) {
if ( exitCode = = ItemWindow : : Accepted ) {
QString err ;
if ( ! bdb - > setItem ( browse , key . toUtf8 ( ) , iw - > ContentArea ( ) - > toPlainText ( ) . toUtf8 ( ) , err ) ) {
QMessageBox qmb ;
qmb . setText ( tr ( " Error saving item content: %1 " ) . arg ( err ) ) ;
qmb . exec ( ) ;
}
}
iw - > deleteLater ( ) ;
} ) ;
2017-05-21 04:44:44 +00:00
iw - > show ( ) ;
} ,
[ = ] ( QString error ) {
QMessageBox qmb ;
qmb . setText ( tr ( " Error loading item content: %1 " ) . arg ( error ) ) ;
qmb . exec ( ) ;
}
) ;
}
2017-05-21 05:08:15 +00:00
void MainWindow : : on_actionAdd_bucket_triggered ( )
{
2017-05-21 05:44:07 +00:00
GET_ITM_TOP_BROWSE_BDB ;
2017-05-21 05:08:15 +00:00
// Prompt for bucket name
QString name = QInputDialog : : getText ( this , tr ( " New bucket " ) , tr ( " Enter a key for the new bucket: " ) ) ;
if ( name . length ( ) = = 0 ) {
return ;
}
// Create
QString err ;
if ( ! bdb - > addBucket ( browse , name . toUtf8 ( ) , err ) ) {
QMessageBox qmb ;
qmb . setText ( tr ( " Error creating bucket: %1 " ) . arg ( err ) ) ;
qmb . exec ( ) ;
return ;
}
// Refresh bucket list
refreshBucketTree ( itm ) ; // sub-tree only
ui - > bucketTree - > expandItem ( itm ) ;
}
void MainWindow : : on_actionDelete_bucket_triggered ( )
{
2017-05-21 05:44:07 +00:00
GET_ITM_TOP_BROWSE_BDB ;
2017-05-21 05:08:15 +00:00
// Prompt for confirmation
2017-05-21 05:14:20 +00:00
QString bucketToDelete = itm - > text ( 0 ) ;
if ( QMessageBox : : question ( this , tr ( " Delete bucket " ) , tr ( " Are you sure you want to remove the bucket '%1'? " ) . arg ( bucketToDelete ) , QMessageBox : : Yes , QMessageBox : : Cancel ) ! = QMessageBox : : Yes ) {
return ;
}
// One level down
browse . pop_back ( ) ;
2017-05-21 05:08:15 +00:00
2017-05-21 05:14:20 +00:00
QString err ;
if ( ! bdb - > deleteBucket ( browse , bucketToDelete . toUtf8 ( ) , err ) ) {
QMessageBox qmb ;
qmb . setText ( tr ( " Error removing bucket: %1 " ) . arg ( err ) ) ;
qmb . exec ( ) ;
2017-05-21 05:08:15 +00:00
return ;
}
2017-05-21 05:14:20 +00:00
// Refresh bucket list
refreshBucketTree ( itm - > parent ( ) ) ; // sub-tree only
ui - > bucketTree - > expandItem ( itm - > parent ( ) ) ;
2017-05-21 05:08:15 +00:00
}
2017-05-21 05:44:07 +00:00
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 ) ) ;
}