diff --git a/src/robomongo/core/domain/App.cpp b/src/robomongo/core/domain/App.cpp index 56bbd3d84..88f5e7b39 100644 --- a/src/robomongo/core/domain/App.cpp +++ b/src/robomongo/core/domain/App.cpp @@ -5,7 +5,9 @@ #include "robomongo/core/domain/MongoShell.h" #include "robomongo/core/domain/MongoCollection.h" #include "robomongo/core/settings/ConnectionSettings.h" +#include "robomongo/core/settings/SettingsManager.h" #include "robomongo/core/EventBus.h" +#include "robomongo/core/AppRegistry.h" #include "robomongo/core/utils/QtUtils.h" #include "robomongo/core/utils/StdUtils.h" #include "robomongo/core/utils/Logger.h" @@ -98,6 +100,17 @@ namespace Robomongo MongoShell *App::openShell(ConnectionSettings *connection, const ScriptInfo &scriptInfo) { + if (!AppRegistry::instance().settingsManager()->useTabbar()) { + for (MongoShellsContainerType::const_iterator it = _shells.begin(); it != _shells.end(); ++it) { + MongoShell *shell = *it; + MongoServer *server = shell->server(); + ConnectionSettings *settings = server->connectionRecord(); + if (QString::fromStdString(shell->query()) == scriptInfo.script() + && shell->title() == scriptInfo.title() + && settings->getFullAddress() == connection->getFullAddress()) + return shell; + } + } MongoServer *server = openServer(connection, false); MongoShell *shell = new MongoShell(server,scriptInfo); _shells.push_back(shell); diff --git a/src/robomongo/core/domain/MongoServer.cpp b/src/robomongo/core/domain/MongoServer.cpp index 9c81d02c1..a6ab56fc7 100644 --- a/src/robomongo/core/domain/MongoServer.cpp +++ b/src/robomongo/core/domain/MongoServer.cpp @@ -25,15 +25,15 @@ namespace Robomongo return _isConnected; } - ConnectionSettings *MongoServer::connectionRecord() const - { - return _client->connectionRecord(); + ConnectionSettings *MongoServer::connectionRecord() const + { + return _client->connectionRecord(); } MongoServer::~MongoServer() - { + { clearDatabases(); - delete _client; + _client->stopAndDelete(); } /** @@ -129,7 +129,7 @@ namespace Robomongo { const ConnectionInfo &info = event->info(); _isConnected = !event->isError(); - if (event->isError()) { + if (event->isError()) { AppRegistry::instance().bus()->publish(new ConnectionFailedEvent(this, event->error())); } else if (_visible) { AppRegistry::instance().bus()->publish(new ConnectionEstablishedEvent(this)); @@ -139,7 +139,7 @@ namespace Robomongo MongoDatabase *db = new MongoDatabase(this, name); addDatabase(db); } - } + } _version = info._version; } diff --git a/src/robomongo/core/mongodb/MongoWorker.cpp b/src/robomongo/core/mongodb/MongoWorker.cpp index 90373105a..65d11797b 100644 --- a/src/robomongo/core/mongodb/MongoWorker.cpp +++ b/src/robomongo/core/mongodb/MongoWorker.cpp @@ -24,11 +24,14 @@ namespace Robomongo _isAdmin(true), _isLoadMongoRcJs(isLoadMongoRcJs), _batchSize(batchSize), - _timerId(-1) - { - _thread = new QThread(this); + _timerId(-1), + _isQuiting(false) + { + _thread = new QThread(); moveToThread(_thread); VERIFY(connect( _thread, SIGNAL(started()), this, SLOT(init()) )); + VERIFY(connect( _thread, SIGNAL(finished()), _thread, SLOT(deleteLater()) )); + VERIFY(connect( _thread, SIGNAL(finished()), this, SLOT(deleteLater()) )); _thread->start(); } @@ -66,7 +69,7 @@ namespace Robomongo } void MongoWorker::init() - { + { try { _scriptEngine = new ScriptEngine(_connection); _scriptEngine->init(_isLoadMongoRcJs); @@ -81,14 +84,16 @@ namespace Robomongo MongoWorker::~MongoWorker() { + killTimer(_timerId); delete _dbclient; delete _connection; - _thread->quit(); - if (!_thread->wait(2000)) - _thread->terminate(); - delete _scriptEngine; - delete _thread; + } + + void MongoWorker::stopAndDelete() + { + _isQuiting = true; + _thread->quit(); } /** @@ -139,7 +144,7 @@ namespace Robomongo } MongoWorker::DatabasesContainerType MongoWorker::getDatabaseNamesSafe() - { + { DatabasesContainerType result; std::string authBase = getAuthBase(); if (!_isAdmin && !authBase.empty()) { @@ -168,7 +173,7 @@ namespace Robomongo // If user not an admin - he doesn't have access to mongodb 'listDatabases' command // Non admin user has access only to the single database he specified while performing auth. std::vector dbNames = getDatabaseNamesSafe(); - + if(dbNames.size()){ reply(event->sender(), new LoadDatabaseNamesResponse(this, dbNames)); }else{ @@ -250,7 +255,7 @@ namespace Robomongo } catch(const mongo::DBException &ex) { reply(event->sender(), new DeleteCollectionIndexResponse(this, event->collection(), std::string() )); LOG_MSG(ex.what(), mongo::LL_ERROR); - } + } } void MongoWorker::handle(EditIndexRequest *event) @@ -265,7 +270,7 @@ namespace Robomongo } catch(const mongo::DBException &ex) { reply(event->sender(), new LoadCollectionIndexesResponse(this, std::vector())); LOG_MSG(ex.what(), mongo::LL_ERROR); - } + } } void MongoWorker::handle(LoadFunctionsRequest *event) @@ -530,7 +535,9 @@ namespace Robomongo */ void MongoWorker::send(Event *event) { - AppRegistry::instance().bus()->send(this, event); + if (!_isQuiting) { + AppRegistry::instance().bus()->send(this, event); + } } /** @@ -538,6 +545,8 @@ namespace Robomongo */ void MongoWorker::reply(QObject *receiver, Event *event) { - AppRegistry::instance().bus()->send(receiver, event); + if (!_isQuiting) { + AppRegistry::instance().bus()->send(receiver, event); + } } } diff --git a/src/robomongo/core/mongodb/MongoWorker.h b/src/robomongo/core/mongodb/MongoWorker.h index 860ca82f8..736f253a5 100644 --- a/src/robomongo/core/mongodb/MongoWorker.h +++ b/src/robomongo/core/mongodb/MongoWorker.h @@ -27,7 +27,9 @@ namespace Robomongo ConnectionSettings *connectionRecord() const {return _connection;} ~MongoWorker(); enum{pingTimeMs = 60*1000}; - + + void stopAndDelete(); + protected Q_SLOTS: // handlers: void init(); /** @@ -145,6 +147,7 @@ namespace Robomongo const bool _isLoadMongoRcJs; const int _batchSize; int _timerId; + QAtomicInteger _isQuiting; ConnectionSettings *_connection; }; diff --git a/src/robomongo/core/settings/SettingsManager.cpp b/src/robomongo/core/settings/SettingsManager.cpp index fca394360..06394da72 100644 --- a/src/robomongo/core/settings/SettingsManager.cpp +++ b/src/robomongo/core/settings/SettingsManager.cpp @@ -202,6 +202,12 @@ namespace Robomongo it = _toolbars.find("logs"); if (_toolbars.end() == it) _toolbars["logs"] = false; + + if (map.contains("useTabbar")) { + _useTabbar = map.value("useTabbar").toBool(); + } else { + _useTabbar = true; // Default + } } /** @@ -258,6 +264,8 @@ namespace Robomongo map.insert("toolbars", _toolbars); + map.insert("useTabbar", _useTabbar); + return map; } @@ -291,10 +299,16 @@ namespace Robomongo _textFontFamily = fontFamily; } - void SettingsManager::setTextFontPointSize(int pointSize) { + void SettingsManager::setTextFontPointSize(int pointSize) + { _textFontPointSize = pointSize > 0 ? pointSize : -1; } + void SettingsManager::setUseTabbar(bool usesTabbar) + { + _useTabbar = usesTabbar; + } + void SettingsManager::reorderConnections(const ConnectionSettingsContainerType &connections) { _connections = connections; diff --git a/src/robomongo/core/settings/SettingsManager.h b/src/robomongo/core/settings/SettingsManager.h index d3eaaa8b4..114df187d 100644 --- a/src/robomongo/core/settings/SettingsManager.h +++ b/src/robomongo/core/settings/SettingsManager.h @@ -107,6 +107,9 @@ namespace Robomongo int textFontPointSize() const { return _textFontPointSize; } void setTextFontPointSize(int pointSize); + bool useTabbar() const { return _useTabbar; } + void setUseTabbar(bool useTabbar); + private: @@ -144,6 +147,7 @@ namespace Robomongo QString _currentStyle; QString _textFontFamily; int _textFontPointSize; + bool _useTabbar; /** * @brief List of connections */ diff --git a/src/robomongo/gui/MainWindow.cpp b/src/robomongo/gui/MainWindow.cpp index b164d2908..9a1800cfc 100644 --- a/src/robomongo/gui/MainWindow.cpp +++ b/src/robomongo/gui/MainWindow.cpp @@ -52,19 +52,25 @@ namespace Robomongo::AppRegistry::instance().settingsManager()->setViewMode(mode); Robomongo::AppRegistry::instance().settingsManager()->save(); } - + void saveAutoExpand(bool isExpand) { Robomongo::AppRegistry::instance().settingsManager()->setAutoExpand(isExpand); Robomongo::AppRegistry::instance().settingsManager()->save(); } - + void saveAutoExec(bool isAutoExec) { Robomongo::AppRegistry::instance().settingsManager()->setAutoExec(isAutoExec); Robomongo::AppRegistry::instance().settingsManager()->save(); } + void saveUseTabbar(bool usesTabbar) + { + Robomongo::AppRegistry::instance().settingsManager()->setUseTabbar(usesTabbar); + Robomongo::AppRegistry::instance().settingsManager()->save(); + } + void saveLineNumbers(bool showLineNumbers) { Robomongo::AppRegistry::instance().settingsManager()->setLineNumbers(showLineNumbers); @@ -156,7 +162,7 @@ namespace Robomongo _connectButton->setFocusPolicy(Qt::NoFocus); _connectButton->setToolTip(QString("Connect to local or remote MongoDB instance (%1 + N)").arg(controlKey)); _connectButton->setToolButtonStyle(Qt::ToolButtonIconOnly); - + #if !defined(Q_OS_MAC) _connectButton->setMenu(_connectionsMenu); _connectButton->setPopupMode(QToolButton::MenuButtonPopup); @@ -266,7 +272,7 @@ namespace Robomongo defaultViewModeMenu->addAction(treeModeAction); defaultViewModeMenu->addAction(tableModeAction); defaultViewModeMenu->addAction(textModeAction); - + optionsMenu->addSeparator(); QActionGroup *modeGroup = new QActionGroup(this); @@ -376,13 +382,19 @@ namespace Robomongo disabelConnectionShortcuts->setChecked(AppRegistry::instance().settingsManager()->disableConnectionShortcuts()); VERIFY(connect(disabelConnectionShortcuts, SIGNAL(triggered()), this, SLOT(setDisableConnectionShortcuts()))); optionsMenu->addAction(disabelConnectionShortcuts); - + QAction *autoExec = new QAction(tr("Automatically execute code in new tab"),this); autoExec->setCheckable(true); autoExec->setChecked(AppRegistry::instance().settingsManager()->autoExec()); VERIFY(connect(autoExec, SIGNAL(triggered()), this, SLOT(toggleAutoExec()))); optionsMenu->addAction(autoExec); + _useTabbarAction = new QAction(tr("Show Tabbar"),this); + _useTabbarAction->setCheckable(true); + _useTabbarAction->setChecked(AppRegistry::instance().settingsManager()->useTabbar()); + VERIFY(connect(_useTabbarAction, SIGNAL(triggered()), this, SLOT(toggleUseTabbar()))); + optionsMenu->addAction(_useTabbarAction); + QAction *preferencesAction = new QAction("Preferences",this); VERIFY(connect(preferencesAction, SIGNAL(triggered()), this, SLOT(openPreferences()))); preferencesAction->setVisible(false); @@ -516,7 +528,7 @@ namespace Robomongo styleAction->setCheckable(true); styleAction->setChecked(style == currentStyle); styleGroup->addAction(styleAction); - styles->addAction(styleAction); + styles->addAction(styleAction); } } @@ -713,19 +725,29 @@ namespace Robomongo QAction *send = qobject_cast(sender()); saveAutoExpand(send->isChecked()); } - + void MainWindow::toggleAutoExec() { QAction *send = qobject_cast(sender()); saveAutoExec(send->isChecked()); } + void MainWindow::toggleUseTabbar() + { + QAction *send = qobject_cast(sender()); + bool useTabbar = send->isChecked(); + if (!useTabbar) + _workArea->ui_closeOtherTabsRequested(_workArea->currentIndex()); + + saveUseTabbar(useTabbar); + } + void MainWindow::toggleLineNumbers() { QAction *send = qobject_cast(sender()); saveLineNumbers(send->isChecked()); } - + void MainWindow::executeScript() { QueryWidget *widget = _workArea->currentQueryWidget(); @@ -768,6 +790,10 @@ namespace Robomongo if (!widget) return; + if (!_useTabbarAction->isChecked()) { + _useTabbarAction->trigger(); + } + widget->duplicate(); } @@ -915,37 +941,37 @@ namespace Robomongo QWidget *titleWidget = new QWidget(this); // this lines simply remove explorerDock->setTitleBarWidget(titleWidget); // title bar widget. explorerDock->setVisible(AppRegistry::instance().settingsManager()->toolbars()["explorer"].toBool()); - + QAction *actionExp = explorerDock->toggleViewAction(); - // Adjust any parameter you want. + // Adjust any parameter you want. actionExp->setText(QString("&Explorer")); - actionExp->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E)); + actionExp->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E)); actionExp->setStatusTip(QString("Press to show/hide Database Explorer panel.")); actionExp->setChecked(explorerDock->isVisible()); VERIFY(connect(actionExp, SIGNAL(triggered(bool)), this, SLOT(onExplorerVisibilityChanged(bool)))); - // Install action in the menu. + // Install action in the menu. _viewMenu->addAction(actionExp); addDockWidget(Qt::LeftDockWidgetArea, explorerDock); - LogWidget *log = new LogWidget(this); + LogWidget *log = new LogWidget(this); VERIFY(connect(&Logger::instance(), SIGNAL(printed(const QString&, mongo::LogLevel)), log, SLOT(addMessage(const QString&, mongo::LogLevel)))); _logDock = new QDockWidget(tr("Logs")); _logDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea); _logDock->setWidget(log); _logDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable); _logDock->setVisible(AppRegistry::instance().settingsManager()->toolbars()["logs"].toBool()); - + QAction *action = _logDock->toggleViewAction(); - // Adjust any parameter you want. + // Adjust any parameter you want. action->setText(QString("&Logs")); - action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); + action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); //action->setStatusTip(QString("Press to show/hide Logs panel.")); //commented for now because this message hides Logs button in status bar :) action->setChecked(_logDock->isVisible()); VERIFY(connect(action, SIGNAL(triggered(bool)), this, SLOT(onLogsVisibilityChanged(bool)))); // Install action in the menu. _viewMenu->addAction(action); - + addDockWidget(Qt::BottomDockWidgetArea, _logDock); } @@ -974,32 +1000,32 @@ namespace Robomongo setCentralWidget(window); } - + void MainWindow::onConnectToolbarVisibilityChanged(bool isVisible) { AppRegistry::instance().settingsManager()->setToolbarSettings("connect", isVisible); AppRegistry::instance().settingsManager()->save(); } - + void MainWindow::onOpenSaveToolbarVisibilityChanged(bool isVisible) { AppRegistry::instance().settingsManager()->setToolbarSettings("open_save", isVisible); AppRegistry::instance().settingsManager()->save(); } - + void MainWindow::onExecToolbarVisibilityChanged(bool isVisible) { AppRegistry::instance().settingsManager()->setToolbarSettings("exec", isVisible); AppRegistry::instance().settingsManager()->save(); } - - void MainWindow::onExplorerVisibilityChanged(bool isVisible) + + void MainWindow::onExplorerVisibilityChanged(bool isVisible) { AppRegistry::instance().settingsManager()->setToolbarSettings("explorer", isVisible); AppRegistry::instance().settingsManager()->save(); } - - void MainWindow::onLogsVisibilityChanged(bool isVisible) + + void MainWindow::onLogsVisibilityChanged(bool isVisible) { AppRegistry::instance().settingsManager()->setToolbarSettings("logs", isVisible); AppRegistry::instance().settingsManager()->save(); diff --git a/src/robomongo/gui/MainWindow.h b/src/robomongo/gui/MainWindow.h index abd9e8240..1d095d42f 100644 --- a/src/robomongo/gui/MainWindow.h +++ b/src/robomongo/gui/MainWindow.h @@ -36,6 +36,7 @@ namespace Robomongo void enterCustomMode(); void toggleAutoExpand(); void toggleAutoExec(); + void toggleUseTabbar(); void toggleLineNumbers(); void executeScript(); void stopScript(); @@ -71,13 +72,13 @@ namespace Robomongo void setUtcTimeZone(); void setLocalTimeZone(); void openPreferences(); - + void onConnectToolbarVisibilityChanged(bool isVisisble); void onOpenSaveToolbarVisibilityChanged(bool isVisisble); void onExecToolbarVisibilityChanged(bool isVisisble); void onExplorerVisibilityChanged(bool isVisisble); void onLogsVisibilityChanged(bool isVisible); - + private: QDockWidget *_logDock; @@ -96,6 +97,7 @@ namespace Robomongo QAction *_executeAction; QAction *_stopAction; QAction *_orientationAction; + QAction *_useTabbarAction; QToolBar *_execToolBar; void updateConnectionsMenu(); diff --git a/src/robomongo/gui/widgets/explorer/ExplorerWidget.cpp b/src/robomongo/gui/widgets/explorer/ExplorerWidget.cpp index cf657cb9b..5e2e26552 100644 --- a/src/robomongo/gui/widgets/explorer/ExplorerWidget.cpp +++ b/src/robomongo/gui/widgets/explorer/ExplorerWidget.cpp @@ -5,6 +5,7 @@ #include #include +#include "robomongo/core/settings/SettingsManager.h" #include "robomongo/core/AppRegistry.h" #include "robomongo/core/domain/App.h" #include "robomongo/core/utils/QtUtils.h" @@ -28,6 +29,7 @@ namespace Robomongo VERIFY(connect(_treeWidget, SIGNAL(itemExpanded(QTreeWidgetItem *)), this, SLOT(ui_itemExpanded(QTreeWidgetItem *)))); VERIFY(connect(_treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(ui_itemDoubleClicked(QTreeWidgetItem *, int)))); + VERIFY(connect(_treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(ui_itemClicked(QTreeWidgetItem *, int)))); setLayout(vlaout); @@ -35,7 +37,7 @@ namespace Robomongo _progressLabel = new QLabel(this); _progressLabel->setMovie(movie); _progressLabel->hide(); - movie->start(); + movie->start(); } void ExplorerWidget::keyPressEvent(QKeyEvent *event) @@ -115,7 +117,7 @@ namespace Robomongo serverItem->expand(); return; } - + ExplorerCollectionDirIndexesTreeItem * dirItem = dynamic_cast(item); if (dirItem) { dirItem->expand(); @@ -129,4 +131,14 @@ namespace Robomongo AppRegistry::instance().app()->openShell(collectionItem->collection()); } } + + void ExplorerWidget::ui_itemClicked(QTreeWidgetItem *item, int cloumn) + { + if (!AppRegistry::instance().settingsManager()->useTabbar()) { + ExplorerCollectionTreeItem *collectionItem = dynamic_cast(item); + if (collectionItem) { + AppRegistry::instance().app()->openShell(collectionItem->collection()); + } + } + } } diff --git a/src/robomongo/gui/widgets/explorer/ExplorerWidget.h b/src/robomongo/gui/widgets/explorer/ExplorerWidget.h index 905cfdc43..74fca3e2c 100644 --- a/src/robomongo/gui/widgets/explorer/ExplorerWidget.h +++ b/src/robomongo/gui/widgets/explorer/ExplorerWidget.h @@ -29,9 +29,10 @@ namespace Robomongo private Q_SLOTS: void ui_itemExpanded(QTreeWidgetItem *item); void ui_itemDoubleClicked(QTreeWidgetItem *item, int column); + void ui_itemClicked(QTreeWidgetItem *item, int column); protected: - virtual void keyPressEvent(QKeyEvent *event); + virtual void keyPressEvent(QKeyEvent *event); private: int _progress; diff --git a/src/robomongo/gui/widgets/workarea/WorkAreaTabWidget.cpp b/src/robomongo/gui/widgets/workarea/WorkAreaTabWidget.cpp index 062964eb1..1cada07a5 100644 --- a/src/robomongo/gui/widgets/workarea/WorkAreaTabWidget.cpp +++ b/src/robomongo/gui/widgets/workarea/WorkAreaTabWidget.cpp @@ -2,6 +2,8 @@ #include +#include "robomongo/core/settings/SettingsManager.h" +#include "robomongo/core/AppRegistry.h" #include "robomongo/core/utils/QtUtils.h" #include "robomongo/core/KeyboardManager.h" #include "robomongo/core/domain/MongoShell.h" @@ -27,6 +29,7 @@ namespace Robomongo setElideMode(Qt::ElideRight); setMovable(true); setDocumentMode(true); + setTabBarAutoHide(true); VERIFY(connect(this, SIGNAL(tabCloseRequested(int)), SLOT(tabBar_tabCloseRequested(int)))); VERIFY(connect(this, SIGNAL(currentChanged(int)), SLOT(ui_currentChanged(int)))); @@ -190,7 +193,7 @@ namespace Robomongo if(!send) return; - setTabText(indexOf(send), text); + setTabText(indexOf(send), text); } void WorkAreaTabWidget::tooltipTextChange(const QString &text) @@ -211,10 +214,14 @@ namespace Robomongo QueryWidget *queryWidget = new QueryWidget(event->shell,this); VERIFY(connect(queryWidget, SIGNAL(titleChanged(const QString &)), this, SLOT(tabTextChange(const QString &)))); VERIFY(connect(queryWidget, SIGNAL(toolTipChanged(const QString &)), this, SLOT(tooltipTextChange(const QString &)))); - + addTab(queryWidget, shellName); setCurrentIndex(count() - 1); + if (!AppRegistry::instance().settingsManager()->useTabbar()) { + ui_closeOtherTabsRequested(currentIndex()); + } + #if !defined(Q_OS_MAC) setTabIcon(count() - 1, GuiRegistry::instance().mongodbIcon()); #endif