Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03e3592443 | ||
|
|
c113244319 | ||
|
|
3a64e1310b | ||
|
|
306b759b74 | ||
|
|
5976884b0f | ||
|
|
ee907c3321 | ||
|
|
86307a724f | ||
|
|
997aa44654 | ||
|
|
feb1d277e9 | ||
|
|
7e1dac26f1 | ||
|
|
a7b95d4caf | ||
|
|
bb042fe70b | ||
|
|
e50ee8fbee | ||
|
|
55d8a6ff76 | ||
|
|
576fc07b5b | ||
|
|
b4978269a5 | ||
|
|
24e9a74a6c | ||
|
|
61e79155b4 | ||
|
|
d23d9a2e7a | ||
|
|
ae13e30494 | ||
|
|
292c664941 | ||
|
|
c78845571e | ||
|
|
a0d5c67e48 | ||
|
|
059a3dcc37 | ||
|
|
d543bb4539 | ||
|
|
3e8f800682 | ||
|
|
368f2abe0d | ||
|
|
1e8af399e7 | ||
|
|
72f669e189 | ||
|
|
c787b54e7c | ||
|
|
3512be30cf | ||
|
|
0bb279eec8 | ||
|
|
75331d9025 | ||
|
|
99a46eafc8 | ||
|
|
ac9300f5be | ||
|
|
4e4e5154f4 | ||
|
|
b54c096762 | ||
|
|
5d409ec1de |
@@ -8,7 +8,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
|
||||
set(PROJECT_VERSION_MAJOR "0")
|
||||
set(PROJECT_VERSION_MINOR "9")
|
||||
set(PROJECT_VERSION_PATCH "0")
|
||||
set(PROJECT_VERSION_BUILD "-RC7")
|
||||
set(PROJECT_VERSION_BUILD "-RC8")
|
||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${PROJECT_VERSION_BUILD}")
|
||||
|
||||
# Modules
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BIN_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # Get directory of this file
|
||||
PROJECT_DIR=$(dirname $BIN_DIR) # Get root directory of project
|
||||
|
||||
VERSION="$(echo $1 | tr '[A-Z]' '[a-z]')"
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "Usage: tag <name>"
|
||||
echo "Example: tag 0.9.0-rc9"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "$(git rev-parse --abbrev-ref HEAD)" != "master" ]; then
|
||||
echo "Error: You are not on master branch"
|
||||
exit
|
||||
fi
|
||||
|
||||
cd $PROJECT_DIR
|
||||
git tag -a "v${VERSION}" -m "${VERSION}"
|
||||
git push --tags
|
||||
@@ -52,6 +52,18 @@ elseif("${CMAKE_BUILD_TYPE}" MATCHES "MinSizeRel")
|
||||
set(BUILD_MINSIZEREL TRUE)
|
||||
endif()
|
||||
|
||||
# Compiler checks
|
||||
# We check Clang using MATCH instead of strict equality, because as of CMake 3.0.0 the
|
||||
# CMAKE_<LANG>_COMPILER_ID value for Apple-provided Clang is AppleClang. To test
|
||||
# for both the Apple-provided Clang and the regular Clang we use MATCH.
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(COMPILER_CLANG TRUE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "^GNU$")
|
||||
set(COMPILER_GCC TRUE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "^MSVC$")
|
||||
set(COMPILER_MSVC TRUE)
|
||||
endif()
|
||||
|
||||
# Link "groups" and "whole-archive" options
|
||||
if(SYSTEM_LINUX OR SYSTEM_FREEBSD OR SYSTEM_OPENBSD)
|
||||
set(LINK_LIBGROUP_START -Wl,--start-group)
|
||||
|
||||
@@ -10,6 +10,7 @@ elseif(SYSTEM_WINDOWS)
|
||||
# The /MP option can reduce the total time to compile the source files. This option
|
||||
# causes the compiler to create one or more copies of itself, each in a separate process.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} psapi.lib bcrypt.lib Iphlpapi.lib dbghelp.lib ws2_32.lib winmm.lib version.lib")
|
||||
endif()
|
||||
|
||||
@@ -5,6 +5,10 @@ set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
#set(sanitize "-fsanitize=address")
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${sanitize}")
|
||||
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${sanitize}")
|
||||
|
||||
set(SOURCES
|
||||
|
||||
# Isolated Scope #1
|
||||
|
||||
@@ -39,11 +39,15 @@ int main(int argc, char *argv[], char** envp)
|
||||
// This can cause a conflict when using POSIX functions, for instance, when
|
||||
// converting between data types such as floats and strings, since the notation
|
||||
// may differ between locales. To get around this problem, call the POSIX
|
||||
// function setlocale(LC_NUMERIC,"C") right after initializing QApplication or
|
||||
// function setlocale(LC_NUMERIC, "C") right after initializing QApplication or
|
||||
// QCoreApplication to reset the locale that is used for number formatting to "C"-locale.
|
||||
// (http://doc.qt.io/qt-5/qcoreapplication.html#locale-settings)
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
app.setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#endif
|
||||
|
||||
// Init GUI style
|
||||
Robomongo::AppStyleUtils::initStyle();
|
||||
|
||||
|
||||
@@ -33,12 +33,19 @@ void precisionAssert(const std::string &text, double d) {
|
||||
std::stringstream s;
|
||||
s.precision(std::numeric_limits<double>::digits10);
|
||||
s << d;
|
||||
if (d == (long long)d)
|
||||
s << ".0";
|
||||
std::cout << "Checking " << text << " - ";
|
||||
assert(text == s.str());
|
||||
std::cout << "Correct. " << std::endl;
|
||||
}
|
||||
|
||||
void testPrecision() {
|
||||
precisionAssert("-9.987654321", -9.987654321);
|
||||
precisionAssert("-1.0", -1.0);
|
||||
precisionAssert("-0.0", -0.0);
|
||||
precisionAssert("0.0", 0.0);
|
||||
precisionAssert("9.0", 9.0);
|
||||
precisionAssert("9.8", 9.8);
|
||||
precisionAssert("9.9", 9.9);
|
||||
precisionAssert("9.98", 9.98);
|
||||
|
||||
@@ -30,4 +30,18 @@ namespace Robomongo
|
||||
|
||||
class MongoDocument;
|
||||
typedef boost::shared_ptr<MongoDocument> MongoDocumentPtr;
|
||||
|
||||
enum ConnectionType {
|
||||
// This type of connection is shown in Explorer and also
|
||||
// opens SSH tunnel for Secondary connections (if needed)
|
||||
ConnectionPrimary = 0,
|
||||
|
||||
// Never shown in Explorer and uses SSH tunnel from
|
||||
// Primary connection (if needed)
|
||||
ConnectionSecondary = 1,
|
||||
|
||||
// The same as Primary, but is specifically for testing
|
||||
// connections.
|
||||
ConnectionTest = 2
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ namespace
|
||||
template<typename type, int size>
|
||||
inline type findTypeInArray(const char *(&arr)[size], const char *text)
|
||||
{
|
||||
for (int i=0; i < size;++i )
|
||||
for (int i = 0; i < size; ++i )
|
||||
{
|
||||
if (strcmp(text,arr[i])==0)
|
||||
if (strcmp(text, arr[i]) == 0)
|
||||
{
|
||||
return static_cast<type>(i);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Robomongo
|
||||
char *data = new char[bytes];
|
||||
|
||||
const char *p = s.c_str();
|
||||
for( size_t i = 0; i < bytes; i++ ) {
|
||||
for (size_t i = 0; i < bytes; i++) {
|
||||
data[i] = mongo::fromHex(p);
|
||||
p += 2;
|
||||
}
|
||||
@@ -159,7 +159,7 @@ namespace Robomongo
|
||||
mongo::BinDataType binType = element.binDataType();
|
||||
|
||||
if (binType != mongo::newUUID && binType != mongo::bdtUUID)
|
||||
throw new std::invalid_argument("Binary subtype should be 3 (bdtUUID) or 4 (newUUID)");
|
||||
throw std::invalid_argument("Binary subtype should be 3 (bdtUUID) or 4 (newUUID)");
|
||||
|
||||
int len;
|
||||
const char *data = element.binData(len);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "robomongo/core/domain/App.h"
|
||||
#include <QHash>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include "robomongo/core/domain/MongoServer.h"
|
||||
#include "robomongo/core/domain/MongoShell.h"
|
||||
@@ -33,7 +34,7 @@ namespace Robomongo
|
||||
}
|
||||
|
||||
App::App(EventBus *const bus) : QObject(),
|
||||
_bus(bus) {
|
||||
_bus(bus), _lastServerHandle(0) {
|
||||
_bus->subscribe(this, EstablishSshConnectionResponse::Type);
|
||||
_bus->subscribe(this, ListenSshConnectionResponse::Type);
|
||||
_bus->subscribe(this, LogEvent::Type);
|
||||
@@ -45,19 +46,63 @@ namespace Robomongo
|
||||
std::for_each(_servers.begin(), _servers.end(), stdutils::default_delete<MongoServer*>());
|
||||
}
|
||||
|
||||
bool App::openServer(ConnectionSettings *connection, ConnectionType type) {
|
||||
|
||||
SshSettings *ssh = connection->sshSettings();
|
||||
|
||||
if (ssh->enabled() && ssh->askPassword() &&
|
||||
(type == ConnectionPrimary || type == ConnectionTest)) {
|
||||
bool ok = false;
|
||||
|
||||
bool isByKey = ssh->authMethod() == "publickey";
|
||||
std::string passText = isByKey ? "passphrase" : "password";
|
||||
|
||||
std::stringstream s;
|
||||
s << "In order to continue, please provide the " << passText;
|
||||
|
||||
if (isByKey)
|
||||
s << " for the key file";
|
||||
|
||||
s << "." << std::endl << std::endl;
|
||||
|
||||
if (ssh->authMethod() == "publickey")
|
||||
s << "Private Key: " << ssh->privateKeyFile() << std::endl;
|
||||
|
||||
s << "Server: " << ssh->host() << std::endl;
|
||||
s << "User: " << ssh->userName() << std::endl;
|
||||
|
||||
|
||||
s << std::endl << "Enter your " << passText << " that will never be stored:";
|
||||
|
||||
QString userInput = QInputDialog::getText(NULL, tr("SSH Authentication"),
|
||||
QtUtils::toQString(s.str()),
|
||||
QLineEdit::Password, "", &ok);
|
||||
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
ssh->setAskedPassword(QtUtils::toStdString(userInput));
|
||||
}
|
||||
|
||||
openServerInternal(connection, type);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and opens new server connection.
|
||||
* @param connection: ConnectionSettings, that will be owned by MongoServer.
|
||||
* @param visible: should this server be visible in UI (explorer) or not.
|
||||
*/
|
||||
MongoServer *App::openServer(ConnectionSettings *connection, bool visible) {
|
||||
if (visible)
|
||||
MongoServer *App::openServerInternal(ConnectionSettings *connection, ConnectionType type) {
|
||||
++_lastServerHandle;
|
||||
|
||||
if (type == ConnectionPrimary)
|
||||
_bus->publish(new ConnectingEvent(this));
|
||||
|
||||
// When connection is not "visible" or do not have
|
||||
// When connection is SECONDARY or do not have
|
||||
// ssh settings enabled, continue without SSH Tunnel
|
||||
if (!visible || !connection->sshSettings()->enabled()) {
|
||||
return continueOpenServer(connection, visible);
|
||||
if (type == ConnectionSecondary || !connection->sshSettings()->enabled()) {
|
||||
return continueOpenServer(_lastServerHandle, connection, type);
|
||||
}
|
||||
|
||||
// Open SSH channel and only after that open connection
|
||||
@@ -67,7 +112,7 @@ namespace Robomongo
|
||||
|
||||
ConnectionSettings* settingsCopy = connection->clone();
|
||||
SshTunnelWorker* sshWorker = new SshTunnelWorker(settingsCopy);
|
||||
_bus->send(sshWorker, new EstablishSshConnectionRequest(this, sshWorker, settingsCopy, visible));
|
||||
_bus->send(sshWorker, new EstablishSshConnectionRequest(this, _lastServerHandle, sshWorker, settingsCopy, type));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -80,43 +125,46 @@ namespace Robomongo
|
||||
_servers.erase(std::remove_if(_servers.begin(), _servers.end(), stdutils::RemoveIfFound<MongoServer*>(server)), _servers.end());
|
||||
}
|
||||
|
||||
MongoShell *App::openShell(MongoCollection *collection,const QString &filePathToSave)
|
||||
void App::openShell(MongoCollection *collection, const QString &filePathToSave)
|
||||
{
|
||||
ConnectionSettings *connection = collection->database()->server()->connectionRecord();
|
||||
connection->setDefaultDatabase(collection->database()->name());
|
||||
QString script = detail::buildCollectionQuery(collection->name(), "find({})");
|
||||
return openShell(connection, ScriptInfo(script, true, CursorPosition(0, -2), QtUtils::toQString(collection->database()->name()),filePathToSave));
|
||||
openShell(connection, ScriptInfo(script, true, CursorPosition(0, -2), QtUtils::toQString(collection->database()->name()), filePathToSave));
|
||||
}
|
||||
|
||||
MongoShell *App::openShell(MongoServer *server,const QString &script, const std::string &dbName,
|
||||
void App::openShell(MongoServer *server, const QString &script, const std::string &dbName,
|
||||
bool execute, const QString &shellName,
|
||||
const CursorPosition &cursorPosition,const QString &filePathToSave)
|
||||
const CursorPosition &cursorPosition, const QString &filePathToSave)
|
||||
{
|
||||
ConnectionSettings *connection = server->connectionRecord();
|
||||
|
||||
if (!dbName.empty())
|
||||
connection->setDefaultDatabase(dbName);
|
||||
|
||||
return openShell(connection, ScriptInfo(script, execute, cursorPosition, shellName,filePathToSave));
|
||||
openShell(connection, ScriptInfo(script, execute, cursorPosition, shellName, filePathToSave));
|
||||
}
|
||||
|
||||
MongoShell *App::openShell(MongoDatabase *database, const QString &script,
|
||||
void App::openShell(MongoDatabase *database, const QString &script,
|
||||
bool execute, const QString &shellName,
|
||||
const CursorPosition &cursorPosition,const QString &filePathToSave)
|
||||
const CursorPosition &cursorPosition, const QString &filePathToSave)
|
||||
{
|
||||
ConnectionSettings *connection = database->server()->connectionRecord();
|
||||
connection->setDefaultDatabase(database->name());
|
||||
return openShell(connection, ScriptInfo(script, execute, cursorPosition, shellName,filePathToSave));
|
||||
openShell(connection, ScriptInfo(script, execute, cursorPosition, shellName, filePathToSave));
|
||||
}
|
||||
|
||||
MongoShell *App::openShell(ConnectionSettings *connection, const ScriptInfo &scriptInfo)
|
||||
void App::openShell(ConnectionSettings *connection, const ScriptInfo &scriptInfo)
|
||||
{
|
||||
MongoServer *server = openServer(connection, false);
|
||||
MongoShell *shell = new MongoShell(server,scriptInfo);
|
||||
MongoServer *server = openServerInternal(connection, ConnectionSecondary);
|
||||
if (!server)
|
||||
return;
|
||||
|
||||
MongoShell *shell = new MongoShell(server, scriptInfo);
|
||||
_shells.push_back(shell);
|
||||
_bus->publish(new OpeningShellEvent(this, shell));
|
||||
shell->execute();
|
||||
return shell;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,7 +174,7 @@ namespace Robomongo
|
||||
void App::closeShell(MongoShell *shell)
|
||||
{
|
||||
// Do nothing, if this shell not owned by this App.
|
||||
MongoShellsContainerType::iterator it = std::find_if(_shells.begin(),_shells.end(),std::bind1st(std::equal_to<MongoShell *>(),shell));
|
||||
MongoShellsContainerType::iterator it = std::find_if(_shells.begin(), _shells.end(), std::bind1st(std::equal_to<MongoShell *>(), shell));
|
||||
if (it == _shells.end())
|
||||
return;
|
||||
|
||||
@@ -135,16 +183,17 @@ namespace Robomongo
|
||||
delete shell;
|
||||
}
|
||||
|
||||
MongoServer* App::continueOpenServer(ConnectionSettings *connection, bool visible, int localport) {
|
||||
MongoServer *App::continueOpenServer(int serverHandle, ConnectionSettings *connection, ConnectionType type, int localport) {
|
||||
ConnectionSettings* settings = connection->clone();
|
||||
|
||||
// Modify connection settings when SSH tunnel is used
|
||||
if (visible && settings->sshSettings()->enabled()) {
|
||||
if ((type == ConnectionPrimary || type == ConnectionTest)
|
||||
&& settings->sshSettings()->enabled()) {
|
||||
settings->setServerHost("127.0.0.1");
|
||||
settings->setServerPort(localport);
|
||||
}
|
||||
|
||||
MongoServer *server = new MongoServer(settings, visible);
|
||||
MongoServer *server = new MongoServer(serverHandle, settings, type);
|
||||
_servers.push_back(server);
|
||||
|
||||
server->runWorkerThread();
|
||||
@@ -156,36 +205,43 @@ namespace Robomongo
|
||||
|
||||
void App::handle(EstablishSshConnectionResponse *event) {
|
||||
if (event->isError()) {
|
||||
_bus->publish(new ConnectionFailedEvent(this, event->error().errorMessage()));
|
||||
_bus->publish(new ConnectionFailedEvent(
|
||||
this, event->serverHandle, event->connectionType, event->error().errorMessage(),
|
||||
ConnectionFailedEvent::SshConnection));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_MSG(QString("SSH tunnel created successfully"), mongo::logger::LogSeverity::Info());
|
||||
|
||||
_bus->send(event->worker, new ListenSshConnectionRequest(this));
|
||||
continueOpenServer(event->settings, event->visible, event->localport);
|
||||
|
||||
// record event->worker and delete when needed
|
||||
continueOpenServer(event->serverHandle, event->settings, event->connectionType, event->localport);
|
||||
_bus->send(event->worker, new ListenSshConnectionRequest(this, event->serverHandle, event->connectionType));
|
||||
}
|
||||
|
||||
void App::handle(LogEvent *event) {
|
||||
if (event->level == LogEvent::ERROR) {
|
||||
if (event->level == LogEvent::RBM_ERROR) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Error());
|
||||
} else if (event->level == LogEvent::WARN) {
|
||||
} else if (event->level == LogEvent::RBM_WARN) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Warning());
|
||||
} else if (event->level == LogEvent::INFO) {
|
||||
} else if (event->level == LogEvent::RBM_INFO) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Info());
|
||||
} else if (event->level == LogEvent::DEBUG) {
|
||||
} else if (event->level == LogEvent::RBM_DEBUG) {
|
||||
LOG_MSG(event->message, mongo::logger::LogSeverity::Log());
|
||||
}
|
||||
}
|
||||
|
||||
void App::handle(ListenSshConnectionResponse *event) {
|
||||
if (event->isError()) {
|
||||
_bus->publish(new ConnectionFailedEvent(this, event->error().errorMessage()));
|
||||
_bus->publish(new ConnectionFailedEvent(this, event->serverHandle, event->connectionType, event->error().errorMessage(),
|
||||
ConnectionFailedEvent::SshChannel));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_MSG(QString("SSH tunnel closed."), mongo::logger::LogSeverity::Error());
|
||||
}
|
||||
|
||||
void App::fireConnectionFailedEvent(int serverHandle, ConnectionType type, std::string errormsg,
|
||||
ConnectionFailedEvent::Reason reason) {
|
||||
_bus->publish(new ConnectionFailedEvent(this, serverHandle, type, errormsg, reason));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,8 +47,9 @@ namespace Robomongo
|
||||
* @brief Creates and opens new server connection.
|
||||
* @param connection: ConnectionSettings, that will be owned by MongoServer.
|
||||
* @param visible: should this server be visible in UI (explorer) or not.
|
||||
* @return Succeeded or not
|
||||
*/
|
||||
MongoServer *openServer(ConnectionSettings *connection, bool visible);
|
||||
bool openServer(ConnectionSettings *connection, ConnectionType type);
|
||||
|
||||
/**
|
||||
* @brief Closes MongoServer connection and frees all resources, owned
|
||||
@@ -59,18 +60,18 @@ namespace Robomongo
|
||||
/**
|
||||
* @brief Open new shell based on specified collection
|
||||
*/
|
||||
MongoShell *openShell(MongoCollection *collection,const QString &filePathToSave=QString());
|
||||
void openShell(MongoCollection *collection, const QString &filePathToSave = QString());
|
||||
|
||||
MongoShell *openShell(MongoServer *server, const QString &script, const std::string &dbName = std::string(),
|
||||
void openShell(MongoServer *server, const QString &script, const std::string &dbName = std::string(),
|
||||
bool execute = true, const QString &shellName = QString(),
|
||||
const CursorPosition &cursorPosition = CursorPosition(), const QString &file = QString());
|
||||
|
||||
MongoShell *openShell(MongoDatabase *database, const QString &script,
|
||||
void openShell(MongoDatabase *database, const QString &script,
|
||||
bool execute = true, const QString &shellName = QString(),
|
||||
const CursorPosition &cursorPosition = CursorPosition(), const QString &filePathToSave = QString());
|
||||
|
||||
MongoShell *openShell(ConnectionSettings *connection, const ScriptInfo &scriptInfo);
|
||||
MongoServersContainerType getServers() const {return _servers; };
|
||||
void openShell(ConnectionSettings *connection, const ScriptInfo &scriptInfo);
|
||||
MongoServersContainerType getServers() const { return _servers; };
|
||||
|
||||
/**
|
||||
* @brief Closes MongoShell and frees all resources, owned by specified MongoShell.
|
||||
@@ -78,13 +79,18 @@ namespace Robomongo
|
||||
*/
|
||||
void closeShell(MongoShell *shell);
|
||||
|
||||
void fireConnectionFailedEvent(int serverHandle, ConnectionType type, std::string errormsg, ConnectionFailedEvent::Reason reason);
|
||||
|
||||
int getLastServerHandle() const { return _lastServerHandle; };
|
||||
|
||||
public Q_SLOTS:
|
||||
void handle(EstablishSshConnectionResponse *event);
|
||||
void handle(ListenSshConnectionResponse *event);
|
||||
void handle(LogEvent *event);
|
||||
|
||||
private:
|
||||
MongoServer* continueOpenServer(ConnectionSettings *connection, bool visible, int localport = 0);
|
||||
MongoServer *openServerInternal(ConnectionSettings *connection, ConnectionType type);
|
||||
MongoServer *continueOpenServer(int serverHandle, ConnectionSettings *connection, ConnectionType type, int localport = 0);
|
||||
|
||||
/**
|
||||
* MongoServers, owned by this App.
|
||||
@@ -97,5 +103,9 @@ namespace Robomongo
|
||||
MongoShellsContainerType _shells;
|
||||
|
||||
EventBus *const _bus;
|
||||
|
||||
// Increase monotonically when new MongoServer is created
|
||||
// Never decreases.
|
||||
int _lastServerHandle;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Robomongo
|
||||
std::vector<MongoDocumentPtr> MongoDocument::fromBsonObj(const std::vector<mongo::BSONObj> &bsonObjs)
|
||||
{
|
||||
std::vector<MongoDocumentPtr> list;
|
||||
for (std::vector<mongo::BSONObj>::const_iterator it=bsonObjs.begin(); it!=bsonObjs.end(); ++it) {
|
||||
for (std::vector<mongo::BSONObj>::const_iterator it = bsonObjs.begin(); it != bsonObjs.end(); ++it) {
|
||||
list.push_back(fromBsonObj(*it));
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Robomongo
|
||||
{
|
||||
MongoFunction::MongoFunction(const mongo::BSONObj &obj)
|
||||
{
|
||||
_name = BsonUtils::getField<mongo::String>(obj,"_id");
|
||||
_name = BsonUtils::getField<mongo::String>(obj, "_id");
|
||||
_code = obj.getField("value")._asCode();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ namespace Robomongo
|
||||
std::string prepareServerAddress(const std::string &address)
|
||||
{
|
||||
size_t pos = address.find_first_of("{");
|
||||
if (pos!=std::string::npos){
|
||||
return address.substr(0,pos);
|
||||
if (pos != std::string::npos) {
|
||||
return address.substr(0, pos);
|
||||
}
|
||||
return address;
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace Robomongo
|
||||
|
||||
CollectionInfo::CollectionInfo(const std::string &server, const std::string &database, const std::string &collection)
|
||||
:_serverAddress(server),
|
||||
_ns(database,collection)
|
||||
_ns(database, collection)
|
||||
{}
|
||||
|
||||
bool CollectionInfo::isValid() const
|
||||
|
||||
@@ -7,19 +7,22 @@
|
||||
#include "robomongo/core/mongodb/MongoWorker.h"
|
||||
#include "robomongo/core/mongodb/SshTunnelWorker.h"
|
||||
#include "robomongo/core/AppRegistry.h"
|
||||
#include "robomongo/core/domain/App.h"
|
||||
#include "robomongo/core/EventBus.h"
|
||||
#include "robomongo/core/utils/QtUtils.h"
|
||||
|
||||
namespace Robomongo {
|
||||
R_REGISTER_EVENT(MongoServerLoadingDatabasesEvent)
|
||||
|
||||
MongoServer::MongoServer(ConnectionSettings *settings, bool visible) : QObject(),
|
||||
MongoServer::MongoServer(int handle, ConnectionSettings *settings, ConnectionType connectionType) : QObject(),
|
||||
_version(0.0f),
|
||||
_visible(visible),
|
||||
_connectionType(connectionType),
|
||||
_client(NULL),
|
||||
_isConnected(false),
|
||||
_settings(settings),
|
||||
_bus(AppRegistry::instance().bus()) { }
|
||||
_handle(handle),
|
||||
_bus(AppRegistry::instance().bus()),
|
||||
_app(AppRegistry::instance().app()) { }
|
||||
|
||||
bool MongoServer::isConnected() const {
|
||||
return _isConnected;
|
||||
@@ -49,7 +52,7 @@ namespace Robomongo {
|
||||
* @throws MongoException, if fails
|
||||
*/
|
||||
void MongoServer::tryConnect() {
|
||||
_bus->send(_client, new EstablishConnectionRequest(this));
|
||||
_bus->send(_client, new EstablishConnectionRequest(this, _connectionType));
|
||||
}
|
||||
|
||||
QStringList MongoServer::getDatabasesNames() const {
|
||||
@@ -62,7 +65,7 @@ namespace Robomongo {
|
||||
}
|
||||
|
||||
void MongoServer::createDatabase(const std::string &dbName) {
|
||||
_bus->send(_client,new CreateDatabaseRequest(this, dbName));
|
||||
_bus->send(_client, new CreateDatabaseRequest(this, dbName));
|
||||
}
|
||||
|
||||
MongoDatabase *MongoServer::findDatabaseByName(const std::string &dbName) const {
|
||||
@@ -76,7 +79,7 @@ namespace Robomongo {
|
||||
}
|
||||
|
||||
void MongoServer::dropDatabase(const std::string &dbName) {
|
||||
_bus->send(_client,new DropDatabaseRequest(this, dbName));
|
||||
_bus->send(_client, new DropDatabaseRequest(this, dbName));
|
||||
}
|
||||
|
||||
void MongoServer::insertDocuments(const std::vector<mongo::BSONObj> &objCont,
|
||||
@@ -87,12 +90,12 @@ namespace Robomongo {
|
||||
}
|
||||
|
||||
void MongoServer::insertDocument(const mongo::BSONObj &obj, const MongoNamespace &ns) {
|
||||
_bus->send(_client,new InsertDocumentRequest(this, obj, ns));
|
||||
_bus->send(_client, new InsertDocumentRequest(this, obj, ns));
|
||||
}
|
||||
|
||||
void MongoServer::saveDocuments(const std::vector<mongo::BSONObj> &objCont, const MongoNamespace &ns) {
|
||||
for (std::vector<mongo::BSONObj>::const_iterator it = objCont.begin(); it != objCont.end(); it++) {
|
||||
saveDocument(*it,ns);
|
||||
saveDocument(*it, ns);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +129,18 @@ namespace Robomongo {
|
||||
ss << "Cannot connect to the MongoDB at " << connectionRecord()->getFullAddress()
|
||||
<< ".\n\nError:\n" << event->error().errorMessage();
|
||||
|
||||
_bus->publish(new ConnectionFailedEvent(this, ss.str()));
|
||||
ConnectionFailedEvent::Reason reason =
|
||||
event->errorReason == EstablishConnectionResponse::MongoAuth ?
|
||||
ConnectionFailedEvent::MongoAuth : ConnectionFailedEvent::MongoConnection;
|
||||
|
||||
// When connection cannot be established, we should
|
||||
// cleanup this instance of MongoServer if it wasn't
|
||||
// shown in UI (i.e. it is not a Secondary connection
|
||||
// that is used for shells tab)
|
||||
if (_connectionType == ConnectionPrimary || _connectionType == ConnectionTest)
|
||||
_app->closeServer(this);
|
||||
|
||||
_app->fireConnectionFailedEvent(_handle, _connectionType, ss.str(), reason);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -134,14 +148,14 @@ namespace Robomongo {
|
||||
_version = info._version;
|
||||
_isConnected = true;
|
||||
|
||||
// Do nothing if this is not "visible" connection
|
||||
if (!_visible) {
|
||||
_bus->publish(new ConnectionEstablishedEvent(this, _connectionType));
|
||||
|
||||
// Do nothing if this is not a "primary" connection
|
||||
if (_connectionType != ConnectionPrimary)
|
||||
return;
|
||||
}
|
||||
|
||||
_bus->publish(new ConnectionEstablishedEvent(this));
|
||||
clearDatabases();
|
||||
for(std::vector<std::string>::const_iterator it = info._databases.begin(); it != info._databases.end(); ++it) {
|
||||
for (std::vector<std::string>::const_iterator it = info._databases.begin(); it != info._databases.end(); ++it) {
|
||||
const std::string &name = *it;
|
||||
MongoDatabase *db = new MongoDatabase(this, name);
|
||||
addDatabase(db);
|
||||
@@ -155,7 +169,7 @@ namespace Robomongo {
|
||||
}
|
||||
|
||||
clearDatabases();
|
||||
for(std::vector<std::string>::iterator it = event->databaseNames.begin(); it != event->databaseNames.end(); ++it) {
|
||||
for (std::vector<std::string>::iterator it = event->databaseNames.begin(); it != event->databaseNames.end(); ++it) {
|
||||
const std::string &name = *it;
|
||||
MongoDatabase *db = new MongoDatabase(this, name);
|
||||
addDatabase(db);
|
||||
@@ -175,6 +189,8 @@ namespace Robomongo {
|
||||
void MongoServer::runWorkerThread() {
|
||||
_client = new MongoWorker(_settings->clone(),
|
||||
AppRegistry::instance().settingsManager()->loadMongoRcJs(),
|
||||
AppRegistry::instance().settingsManager()->batchSize());
|
||||
AppRegistry::instance().settingsManager()->batchSize(),
|
||||
AppRegistry::instance().settingsManager()->mongoTimeoutSec(),
|
||||
AppRegistry::instance().settingsManager()->shellTimeoutSec());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Robomongo
|
||||
class LoadDatabaseNamesResponse;
|
||||
class InsertDocumentResponse;
|
||||
class EventBus;
|
||||
class App;
|
||||
|
||||
/**
|
||||
* @brief MongoServer represents active connection to MongoDB server.
|
||||
@@ -29,7 +30,7 @@ namespace Robomongo
|
||||
* @param visible
|
||||
* @param defaultDatabase
|
||||
*/
|
||||
MongoServer(ConnectionSettings *connectionRecord, bool visible);
|
||||
MongoServer(int handle, ConnectionSettings *connectionRecord, ConnectionType connectionType);
|
||||
~MongoServer();
|
||||
|
||||
void runWorkerThread();
|
||||
@@ -63,7 +64,6 @@ namespace Robomongo
|
||||
* @brief Loads databases of this server asynchronously.
|
||||
*/
|
||||
void loadDatabases();
|
||||
bool visible() const { return _visible; }
|
||||
MongoWorker *const client() const { return _client; }
|
||||
|
||||
protected Q_SLOTS:
|
||||
@@ -76,13 +76,15 @@ namespace Robomongo
|
||||
void clearDatabases();
|
||||
void addDatabase(MongoDatabase *database);
|
||||
|
||||
MongoWorker* _client;
|
||||
ConnectionSettings* _settings;
|
||||
EventBus* _bus;
|
||||
MongoWorker *_client;
|
||||
ConnectionSettings *_settings;
|
||||
EventBus *_bus;
|
||||
App *_app;
|
||||
|
||||
float _version;
|
||||
bool _visible;
|
||||
ConnectionType _connectionType;
|
||||
bool _isConnected;
|
||||
int _handle;
|
||||
|
||||
QList<MongoDatabase *> _databases;
|
||||
};
|
||||
|
||||
@@ -38,12 +38,12 @@ namespace Robomongo
|
||||
if (_scriptInfo.execute()) {
|
||||
AppRegistry::instance().bus()->publish(new ScriptExecutingEvent(this));
|
||||
AppRegistry::instance().bus()->send(_server->client(), new ExecuteScriptRequest(this, query(), dbName));
|
||||
if(!_scriptInfo.script().isEmpty())
|
||||
if (!_scriptInfo.script().isEmpty())
|
||||
LOG_MSG(_scriptInfo.script(), mongo::logger::LogSeverity::Info());
|
||||
} else {
|
||||
AppRegistry::instance().bus()->publish(new ScriptExecutingEvent(this));
|
||||
_scriptInfo.setScript("");
|
||||
AppRegistry::instance().bus()->send(_server->client(), new ExecuteScriptRequest(this,query() , dbName));
|
||||
AppRegistry::instance().bus()->send(_server->client(), new ExecuteScriptRequest(this, query() , dbName));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Robomongo
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MongoShell(MongoServer *server,const ScriptInfo &scriptInfo);
|
||||
MongoShell(MongoServer *server, const ScriptInfo &scriptInfo);
|
||||
|
||||
void open(const std::string &script, const std::string &dbName = std::string());
|
||||
void query(int resultIndex, const MongoQueryInfo &info);
|
||||
@@ -19,7 +19,7 @@ namespace Robomongo
|
||||
MongoServer *server() const { return _server; }
|
||||
std::string query() const;
|
||||
void execute(const std::string &dbName = std::string());
|
||||
bool isExecutable() const {return _scriptInfo.execute(); }
|
||||
bool isExecutable() const { return _scriptInfo.execute(); }
|
||||
const QString &title() const { return _scriptInfo.title(); }
|
||||
const CursorPosition &cursor() const { return _scriptInfo.cursor(); }
|
||||
void setScript(const QString &script) { return _scriptInfo.setScript(script); }
|
||||
|
||||
@@ -12,15 +12,15 @@ namespace Robomongo
|
||||
_version(version), _readOnly(false)
|
||||
{
|
||||
_id = obj.getField("_id").OID();
|
||||
_name = BsonUtils::getField<mongo::String>(obj,"user");
|
||||
_passwordHash = BsonUtils::getField<mongo::String>(obj,"pwd");
|
||||
_name = BsonUtils::getField<mongo::String>(obj, "user");
|
||||
_passwordHash = BsonUtils::getField<mongo::String>(obj, "pwd");
|
||||
if (_version<minimumSupportedVersion) {
|
||||
_readOnly = BsonUtils::getField<mongo::Bool>(obj,"readOnly");
|
||||
_readOnly = BsonUtils::getField<mongo::Bool>(obj, "readOnly");
|
||||
}
|
||||
else {
|
||||
_userSource = BsonUtils::getField<mongo::String>(obj,"userSource");
|
||||
_userSource = BsonUtils::getField<mongo::String>(obj, "userSource");
|
||||
std::vector<mongo::BSONElement> roles = BsonUtils::getField<mongo::Array>(obj, "roles");
|
||||
for (std::vector<mongo::BSONElement>::const_iterator it = roles.begin(); it!= roles.end(); ++it)
|
||||
for (std::vector<mongo::BSONElement>::const_iterator it = roles.begin(); it != roles.end(); ++it)
|
||||
{
|
||||
_role.push_back(BsonUtils::bsonelement_cast<std::string>(*it));
|
||||
}
|
||||
@@ -28,7 +28,7 @@ namespace Robomongo
|
||||
}
|
||||
|
||||
MongoUser::MongoUser(const float version) :
|
||||
_version(version),_readOnly(false),_role() {}
|
||||
_version(version), _readOnly(false), _role() {}
|
||||
|
||||
mongo::BSONObj MongoUser::toBson() const
|
||||
{
|
||||
@@ -50,7 +50,7 @@ namespace Robomongo
|
||||
builder.append("userSource", _userSource);
|
||||
|
||||
mongo::BSONArrayBuilder builderA;
|
||||
for (RoleType::const_iterator it = _role.begin(); it!=_role.end(); ++it)
|
||||
for (RoleType::const_iterator it = _role.begin(); it != _role.end(); ++it)
|
||||
{
|
||||
builderA << *it;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Robomongo
|
||||
|
||||
bool isMultiSelection(const QModelIndexList &indexes)
|
||||
{
|
||||
return indexes.count()>1;
|
||||
return indexes.count() > 1;
|
||||
}
|
||||
|
||||
bool isDocumentType(BsonTreeItem *item)
|
||||
@@ -55,20 +55,20 @@ namespace Robomongo
|
||||
QModelIndexList uniqueRows(QModelIndexList indexes, bool returnSuperParents)
|
||||
{
|
||||
QModelIndexList result;
|
||||
for (QModelIndexList::const_iterator it = indexes.begin(); it!=indexes.end(); ++it)
|
||||
for (QModelIndexList::const_iterator it = indexes.begin(); it != indexes.end(); ++it)
|
||||
{
|
||||
QModelIndex isUnique = *it;
|
||||
Robomongo::BsonTreeItem *item = Robomongo::QtUtils::item<Robomongo::BsonTreeItem*>(isUnique);
|
||||
if(item){
|
||||
for (QModelIndexList::const_iterator jt = result.begin(); jt!=result.end(); ++jt)
|
||||
if (item) {
|
||||
for (QModelIndexList::const_iterator jt = result.begin(); jt != result.end(); ++jt)
|
||||
{
|
||||
Robomongo::BsonTreeItem *jItem = Robomongo::QtUtils::item<Robomongo::BsonTreeItem*>(*jt);
|
||||
if (jItem && jItem->superParent() == item->superParent()){
|
||||
if (jItem && jItem->superParent() == item->superParent()) {
|
||||
isUnique = QModelIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isUnique.isValid()){
|
||||
if (isUnique.isValid()) {
|
||||
if (returnSuperParents) {
|
||||
// Move index onto "super parent" element before pushing it into result set
|
||||
QModelIndex parent = isUnique.parent();
|
||||
@@ -187,7 +187,7 @@ namespace Robomongo
|
||||
break;
|
||||
}
|
||||
|
||||
isNeededRefresh=true;
|
||||
isNeededRefresh = true;
|
||||
_shell->server()->removeDocuments(query, _queryInfo._info._ns);
|
||||
}
|
||||
|
||||
@@ -240,11 +240,11 @@ namespace Robomongo
|
||||
int answer = QMessageBox::question(dynamic_cast<QWidget*>(_observer), "Delete", QString("Do you want to delete %1 selected documents?").arg(selectedIndexes.count()));
|
||||
if (answer == QMessageBox::Yes) {
|
||||
std::vector<BsonTreeItem*> items;
|
||||
for (QModelIndexList::const_iterator it = selectedIndexes.begin(); it!= selectedIndexes.end(); ++it) {
|
||||
for (QModelIndexList::const_iterator it = selectedIndexes.begin(); it != selectedIndexes.end(); ++it) {
|
||||
BsonTreeItem *item = QtUtils::item<BsonTreeItem*>(*it);
|
||||
items.push_back(item);
|
||||
}
|
||||
deleteDocuments(items,true);
|
||||
deleteDocuments(items, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace Robomongo
|
||||
BsonTreeItem *documentItem = QtUtils::item<BsonTreeItem*>(selectedIndex);
|
||||
std::vector<BsonTreeItem*> vec;
|
||||
vec.push_back(documentItem);
|
||||
return deleteDocuments(vec,false);
|
||||
return deleteDocuments(vec, false);
|
||||
}
|
||||
|
||||
void Notifier::onEditDocument()
|
||||
@@ -376,19 +376,19 @@ namespace Robomongo
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
|
||||
// new Date(parseInt(this.valueOf().slice(0,8), 16)*1000);
|
||||
QString hexTimestamp = documentItem->value().mid(10,8);
|
||||
QString hexTimestamp = documentItem->value().mid(10, 8);
|
||||
bool ok;
|
||||
long long milliTimestamp = (long long)hexTimestamp.toLongLong(&ok,16)*1000;
|
||||
long long milliTimestamp = (long long)hexTimestamp.toLongLong(&ok, 16)*1000;
|
||||
|
||||
bool isSupportedDate = (miutil::minDate < milliTimestamp) && (milliTimestamp < miutil::maxDate);
|
||||
|
||||
boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
|
||||
boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
|
||||
boost::posix_time::time_duration diff = boost::posix_time::millisec(milliTimestamp);
|
||||
boost::posix_time::ptime time = epoch + diff;
|
||||
|
||||
if(isSupportedDate)
|
||||
if (isSupportedDate)
|
||||
{
|
||||
std::string date = miutil::isotimeString(time,false,false);
|
||||
std::string date = miutil::isotimeString(time, false, false);
|
||||
clipboard->setText("ISODate(\""+QString::fromStdString(date)+"\")");
|
||||
}
|
||||
else {
|
||||
@@ -411,13 +411,13 @@ namespace Robomongo
|
||||
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
mongo::BSONObj obj = documentItem->root();
|
||||
if (documentItem != documentItem->superParent()){
|
||||
obj = obj[QtUtils::toStdString(documentItem->key())].Obj();
|
||||
if (documentItem != documentItem->superParent()) {
|
||||
obj = obj[documentItem->fieldName()].Obj();
|
||||
}
|
||||
bool isArray = BsonUtils::isArray(documentItem->type());
|
||||
std::string str = BsonUtils::jsonString(obj, mongo::TenGen, 1,
|
||||
AppRegistry::instance().settingsManager()->uuidEncoding(),
|
||||
AppRegistry::instance().settingsManager()->timeZone(),isArray);
|
||||
AppRegistry::instance().settingsManager()->timeZone(), isArray);
|
||||
|
||||
const QString &json = QtUtils::toQString(str);
|
||||
clipboard->setText(json);
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
ScriptInfo::ScriptInfo(const QString &script, bool execute,const CursorPosition &position,
|
||||
ScriptInfo::ScriptInfo(const QString &script, bool execute, const CursorPosition &position,
|
||||
const QString &title, const QString &filePath) :
|
||||
_script(script),
|
||||
_execute(execute),
|
||||
@@ -73,10 +73,10 @@ namespace Robomongo
|
||||
bool ScriptInfo::loadFromFile(const QString &filePath)
|
||||
{
|
||||
bool result = false;
|
||||
QString filepath = QFileDialog::getOpenFileName(QApplication::activeWindow(), filePath,QString(), filterForScripts);
|
||||
QString filepath = QFileDialog::getOpenFileName(QApplication::activeWindow(), filePath, QString(), filterForScripts);
|
||||
if (!filepath.isEmpty()) {
|
||||
QString out;
|
||||
if (loadFromFileText(filepath,out)) {
|
||||
if (loadFromFileText(filepath, out)) {
|
||||
_script = out;
|
||||
_filePath = filepath;
|
||||
result = true;
|
||||
@@ -95,7 +95,7 @@ namespace Robomongo
|
||||
QString filepath = QFileDialog::getSaveFileName(QApplication::activeWindow(),
|
||||
QObject::tr("Save As"), _filePath, filterForScripts);
|
||||
|
||||
if (saveToFileText(filepath,_script)) {
|
||||
if (saveToFileText(filepath, _script)) {
|
||||
_filePath = filepath;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -55,10 +55,12 @@ namespace mongo {
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
ScriptEngine::ScriptEngine(ConnectionSettings *connection) :
|
||||
ScriptEngine::ScriptEngine(ConnectionSettings *connection, int timeoutSec) :
|
||||
_connection(connection),
|
||||
_scope(NULL),
|
||||
_engine(NULL),
|
||||
_timeoutSec(timeoutSec),
|
||||
_initialized(false),
|
||||
_mutex(QMutex::Recursive) { }
|
||||
|
||||
ScriptEngine::~ScriptEngine()
|
||||
@@ -141,13 +143,28 @@ namespace Robomongo
|
||||
|
||||
// Save original autocomplete function so it can be restored if overwritten by user preference
|
||||
_scope->exec("DB.autocompleteOriginal = DB.autocomplete;", "(saveOriginalAutocomplete)", false, false, false);
|
||||
|
||||
// Cache result of original "DB.autocomplete"
|
||||
// Cache invalidated by the invalidateDbCollectionsCache() method.
|
||||
std::string cacheAutocompletion =
|
||||
"__robomongoAutocompletionCache = null;"
|
||||
"DB.autocompleteCached = function(obj) { "
|
||||
" if (__robomongoAutocompletionCache == null) {"
|
||||
" __robomongoAutocompletionCache = DB.autocompleteOriginal(obj);"
|
||||
" }"
|
||||
" return __robomongoAutocompletionCache;"
|
||||
"}";
|
||||
|
||||
_scope->exec(cacheAutocompletion, "", false, false, false);
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
MongoShellExecResult ScriptEngine::exec(const std::string &originalScript, const std::string &dbName)
|
||||
{
|
||||
QMutexLocker lock(&_mutex);
|
||||
|
||||
if(!_scope)
|
||||
if (!_scope)
|
||||
return MongoShellExecResult();
|
||||
|
||||
/*
|
||||
@@ -177,7 +194,7 @@ namespace Robomongo
|
||||
|
||||
use(dbName);
|
||||
|
||||
for(std::vector<std::string>::const_iterator it = statements.begin(); it != statements.end(); ++it)
|
||||
for (std::vector<std::string>::const_iterator it = statements.begin(); it != statements.end(); ++it)
|
||||
{
|
||||
std::string statement = *it;
|
||||
// clear global objects
|
||||
@@ -190,8 +207,8 @@ namespace Robomongo
|
||||
try {
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
if ( _scope->exec( statement , "(shell)" , false , true , false, 0 ) ) {
|
||||
_scope->exec( "__robomongoLastRes = __lastres__; shellPrintHelper( __lastres__ );" , "(shell2)" , true , true , false, 0);
|
||||
if ( _scope->exec( statement , "(shell)" , false , true , false, _timeoutSec * 1000) ) {
|
||||
_scope->exec( "__robomongoLastRes = __lastres__; shellPrintHelper( __lastres__ );" , "(shell2)" , true , true , false, _timeoutSec * 1000);
|
||||
}
|
||||
|
||||
qint64 elapsed = timer.elapsed();
|
||||
@@ -252,7 +269,7 @@ namespace Robomongo
|
||||
void ScriptEngine::ping()
|
||||
{
|
||||
QMutexLocker lock(&_mutex);
|
||||
_scope->exec("if (db) { db.runCommand({ping:1}); }", "(ping)", false, false, false);
|
||||
_scope->exec("if (db) { db.runCommand({ping:1}); }", "(ping)", false, false, false, 3000);
|
||||
}
|
||||
|
||||
QStringList ScriptEngine::complete(const std::string &prefix, const AutocompletionMode mode)
|
||||
@@ -262,7 +279,7 @@ namespace Robomongo
|
||||
|
||||
try {
|
||||
if (mode == AutocompleteAll)
|
||||
_scope->exec("DB.autocomplete = DB.autocompleteOriginal;", "", false, false, false);
|
||||
_scope->exec("DB.autocomplete = DB.autocompleteCached;", "", false, false, false);
|
||||
else if (mode == AutocompleteNoCollectionNames)
|
||||
_scope->exec("DB.autocomplete = function(obj){return [];}", "", false, false, false);
|
||||
|
||||
@@ -413,4 +430,11 @@ namespace Robomongo
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptEngine::invalidateDbCollectionsCache() {
|
||||
if (!_initialized)
|
||||
return;
|
||||
|
||||
_scope->exec("__robomongoAutocompletionCache = null;", "", false, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Robomongo
|
||||
{
|
||||
|
||||
public:
|
||||
ScriptEngine(ConnectionSettings *connection);
|
||||
ScriptEngine(ConnectionSettings *connection, int timeoutSec);
|
||||
~ScriptEngine();
|
||||
|
||||
void init(bool isLoadMongoJs);
|
||||
@@ -27,6 +27,8 @@ namespace Robomongo
|
||||
void ping();
|
||||
QStringList complete(const std::string &prefix, const AutocompletionMode mode);
|
||||
|
||||
void invalidateDbCollectionsCache();
|
||||
|
||||
private:
|
||||
ConnectionSettings *_connection;
|
||||
|
||||
@@ -39,8 +41,10 @@ namespace Robomongo
|
||||
std::vector<std::string> statementize2(const std::string &script);
|
||||
// void parseTree(JSParseNode * root, int indent, const std::string &script, std::vector<std::string> &list, bool topList);
|
||||
|
||||
int _timeoutSec;
|
||||
mongo::ScriptEngine *_engine;
|
||||
mongo::Scope *_scope;
|
||||
QMutex _mutex;
|
||||
bool _initialized;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -30,25 +30,39 @@ namespace Robomongo
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
EstablishConnectionRequest(QObject *sender) :
|
||||
Event(sender) {}
|
||||
EstablishConnectionRequest(QObject *sender, ConnectionType connectionType) :
|
||||
Event(sender),
|
||||
connectionType(connectionType) {}
|
||||
|
||||
ConnectionType connectionType;
|
||||
};
|
||||
|
||||
class EstablishConnectionResponse : public Event
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
EstablishConnectionResponse(QObject *sender, const ConnectionInfo &info) :
|
||||
Event(sender),
|
||||
_info(info) {}
|
||||
enum ErrorReason {
|
||||
MongoConnection = 0,
|
||||
MongoAuth = 1,
|
||||
};
|
||||
|
||||
EstablishConnectionResponse(QObject *sender, const EventError &error) :
|
||||
Event(sender, error),_info() {}
|
||||
EstablishConnectionResponse(QObject *sender, const ConnectionInfo &info, ConnectionType connectionType) :
|
||||
Event(sender),
|
||||
_info(info),
|
||||
connectionType(connectionType) {}
|
||||
|
||||
EstablishConnectionResponse(QObject *sender, const EventError &error, ConnectionType connectionType, ErrorReason errorReason) :
|
||||
Event(sender, error),
|
||||
_info(),
|
||||
connectionType(connectionType),
|
||||
errorReason(errorReason) {}
|
||||
|
||||
const ConnectionInfo &info() const{
|
||||
return _info;
|
||||
}
|
||||
const ConnectionInfo _info;
|
||||
ConnectionType connectionType;
|
||||
ErrorReason errorReason;
|
||||
};
|
||||
|
||||
|
||||
@@ -109,7 +123,7 @@ namespace Robomongo
|
||||
_databaseName(databaseName),
|
||||
_collectionInfos(collectionInfos) { }
|
||||
|
||||
LoadCollectionNamesResponse(QObject *sender,const EventError &error) :
|
||||
LoadCollectionNamesResponse(QObject *sender, const EventError &error) :
|
||||
Event(sender, error) {}
|
||||
|
||||
std::string databaseName() const { return _databaseName; }
|
||||
@@ -125,7 +139,7 @@ namespace Robomongo
|
||||
R_EVENT
|
||||
public:
|
||||
LoadCollectionIndexesRequest(QObject *sender, const MongoCollectionInfo &collection) :
|
||||
Event(sender),_collection(collection) {}
|
||||
Event(sender), _collection(collection) {}
|
||||
MongoCollectionInfo collection() const { return _collection; }
|
||||
private:
|
||||
const MongoCollectionInfo _collection;
|
||||
@@ -148,7 +162,7 @@ namespace Robomongo
|
||||
class EnsureIndexRequest : public Event
|
||||
{
|
||||
R_EVENT
|
||||
EnsureIndexRequest(QObject *sender,const EnsureIndexInfo &oldInfo,const EnsureIndexInfo &newInfo) : Robomongo::Event(sender),oldInfo_(oldInfo),newInfo_(newInfo) {}
|
||||
EnsureIndexRequest(QObject *sender, const EnsureIndexInfo &oldInfo, const EnsureIndexInfo &newInfo) : Robomongo::Event(sender), oldInfo_(oldInfo), newInfo_(newInfo) {}
|
||||
const EnsureIndexInfo &oldInfo() const
|
||||
{
|
||||
return oldInfo_;
|
||||
@@ -172,7 +186,7 @@ namespace Robomongo
|
||||
_name(name) {}
|
||||
|
||||
MongoCollectionInfo collection() const { return _collection; }
|
||||
std::string name() const {return _name;}
|
||||
std::string name() const { return _name; }
|
||||
private:
|
||||
const MongoCollectionInfo _collection;
|
||||
std::string _name;
|
||||
@@ -182,14 +196,14 @@ namespace Robomongo
|
||||
{
|
||||
R_EVENT
|
||||
public:
|
||||
DeleteCollectionIndexResponse(QObject *sender, const MongoCollectionInfo &collection,const std::string &index) :
|
||||
Event(sender),_collection(collection),_index(index) {}
|
||||
DeleteCollectionIndexResponse(QObject *sender, const MongoCollectionInfo &collection, const std::string &index) :
|
||||
Event(sender), _collection(collection), _index(index) {}
|
||||
|
||||
DeleteCollectionIndexResponse(QObject *sender, const EventError &error) :
|
||||
Event(sender, error) {}
|
||||
|
||||
MongoCollectionInfo collection() const { return _collection; }
|
||||
std::string index() const {return _index;}
|
||||
std::string index() const { return _index; }
|
||||
private:
|
||||
MongoCollectionInfo _collection;
|
||||
std::string _index;
|
||||
@@ -199,11 +213,11 @@ namespace Robomongo
|
||||
{
|
||||
R_EVENT
|
||||
public:
|
||||
EditIndexRequest(QObject *sender, const MongoCollectionInfo &collection,const std::string &oldIndex,const std::string &newIndex) :
|
||||
Event(sender),_collection(collection),_oldIndex(oldIndex),_newIndex(newIndex) {}
|
||||
EditIndexRequest(QObject *sender, const MongoCollectionInfo &collection, const std::string &oldIndex, const std::string &newIndex) :
|
||||
Event(sender), _collection(collection), _oldIndex(oldIndex), _newIndex(newIndex) {}
|
||||
MongoCollectionInfo collection() const { return _collection; }
|
||||
std::string oldIndex() const {return _oldIndex;}
|
||||
std::string newIndex() const {return _newIndex;}
|
||||
std::string oldIndex() const { return _oldIndex; }
|
||||
std::string newIndex() const { return _newIndex; }
|
||||
private:
|
||||
const MongoCollectionInfo _collection;
|
||||
std::string _oldIndex;
|
||||
@@ -240,7 +254,7 @@ namespace Robomongo
|
||||
_databaseName(databaseName),
|
||||
_users(users) { }
|
||||
|
||||
LoadUsersResponse(QObject *sender,const EventError &error) :
|
||||
LoadUsersResponse(QObject *sender, const EventError &error) :
|
||||
Event(sender, error) {}
|
||||
|
||||
std::string databaseName() const { return _databaseName; }
|
||||
@@ -282,7 +296,7 @@ namespace Robomongo
|
||||
_databaseName(databaseName),
|
||||
_functions(functions) { }
|
||||
|
||||
LoadFunctionsResponse(QObject *sender,const EventError &error) :
|
||||
LoadFunctionsResponse(QObject *sender, const EventError &error) :
|
||||
Event(sender, error) {}
|
||||
|
||||
std::string databaseName() const { return _databaseName; }
|
||||
@@ -580,7 +594,7 @@ namespace Robomongo
|
||||
_to(databaseTo, collection) {}
|
||||
|
||||
MongoWorker *worker() const { return _worker; }
|
||||
MongoNamespace from() const { return _from;}
|
||||
MongoNamespace from() const { return _from; }
|
||||
MongoNamespace to() const { return _to; }
|
||||
private:
|
||||
MongoWorker *_worker;
|
||||
@@ -806,7 +820,7 @@ namespace Robomongo
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
AutocompleteResponse(QObject *sender,const QStringList &list, const std::string &prefix) :
|
||||
AutocompleteResponse(QObject *sender, const QStringList &list, const std::string &prefix) :
|
||||
Event(sender),
|
||||
list(list),
|
||||
prefix(prefix) {}
|
||||
@@ -879,14 +893,25 @@ namespace Robomongo
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
ConnectionFailedEvent(QObject *sender, const std::string& message) :
|
||||
Event(sender),
|
||||
message(message) {}
|
||||
enum Reason {
|
||||
MongoConnection = 1,
|
||||
MongoAuth = 2,
|
||||
SshConnection = 3,
|
||||
SshChannel = 4
|
||||
};
|
||||
|
||||
ConnectionFailedEvent(QObject *sender, const EventError &error) :
|
||||
Event(sender, error) {}
|
||||
ConnectionFailedEvent(QObject *sender, int serverHandle, ConnectionType connectionType,
|
||||
const std::string& message, Reason reason) :
|
||||
Event(sender),
|
||||
message(message),
|
||||
reason(reason),
|
||||
serverHandle(serverHandle),
|
||||
connectionType(connectionType) {}
|
||||
|
||||
std::string message;
|
||||
Reason reason;
|
||||
ConnectionType connectionType;
|
||||
int serverHandle;
|
||||
};
|
||||
|
||||
// class ScriptExecute
|
||||
@@ -895,11 +920,13 @@ namespace Robomongo
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
ConnectionEstablishedEvent(MongoServer *server) :
|
||||
ConnectionEstablishedEvent(MongoServer *server, ConnectionType type) :
|
||||
Event((QObject *)server),
|
||||
server(server) { }
|
||||
server(server),
|
||||
connectionType(type) { }
|
||||
|
||||
MongoServer *server;
|
||||
ConnectionType connectionType;
|
||||
};
|
||||
|
||||
class DatabaseListLoadedEvent : public Event
|
||||
@@ -996,38 +1023,43 @@ namespace Robomongo
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
EstablishSshConnectionRequest(QObject *sender, SshTunnelWorker* worker, ConnectionSettings* settings, bool visible) :
|
||||
EstablishSshConnectionRequest(QObject *sender, int serverHandle, SshTunnelWorker* worker, ConnectionSettings* settings, ConnectionType connectionType) :
|
||||
Event(sender),
|
||||
worker(worker),
|
||||
settings(settings),
|
||||
visible(visible) {}
|
||||
serverHandle(serverHandle),
|
||||
connectionType(connectionType) {}
|
||||
|
||||
ConnectionSettings* settings;
|
||||
bool visible;
|
||||
ConnectionType connectionType;
|
||||
SshTunnelWorker* worker;
|
||||
int serverHandle;
|
||||
};
|
||||
|
||||
class EstablishSshConnectionResponse : public Event
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
EstablishSshConnectionResponse(QObject *sender, SshTunnelWorker* worker, ConnectionSettings* settings, bool visible, int localport) :
|
||||
EstablishSshConnectionResponse(QObject *sender, int serverHandle, SshTunnelWorker* worker, ConnectionSettings* settings, ConnectionType connectionType, int localport) :
|
||||
Event(sender),
|
||||
worker(worker),
|
||||
settings(settings),
|
||||
visible(visible),
|
||||
connectionType(connectionType),
|
||||
serverHandle(serverHandle),
|
||||
localport(localport) {}
|
||||
|
||||
EstablishSshConnectionResponse(QObject *sender, const EventError &error, SshTunnelWorker* worker, ConnectionSettings* settings, bool visible) :
|
||||
EstablishSshConnectionResponse(QObject *sender, int serverHandle, const EventError &error, SshTunnelWorker* worker, ConnectionSettings* settings, ConnectionType connectionType) :
|
||||
Event(sender, error),
|
||||
worker(worker),
|
||||
settings(settings),
|
||||
visible(visible) {}
|
||||
serverHandle(serverHandle),
|
||||
connectionType(connectionType) {}
|
||||
|
||||
ConnectionSettings* settings;
|
||||
bool visible;
|
||||
ConnectionType connectionType;
|
||||
SshTunnelWorker* worker;
|
||||
int localport;
|
||||
int serverHandle;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1038,23 +1070,34 @@ namespace Robomongo
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
ListenSshConnectionRequest(QObject *sender) :
|
||||
Event(sender) {}
|
||||
ListenSshConnectionRequest(QObject *sender, int serverHandle, ConnectionType connectionType) :
|
||||
Event(sender),
|
||||
serverHandle(serverHandle),
|
||||
connectionType(connectionType) {}
|
||||
|
||||
ConnectionType connectionType;
|
||||
int serverHandle;
|
||||
};
|
||||
|
||||
class ListenSshConnectionResponse : public Event
|
||||
{
|
||||
R_EVENT
|
||||
|
||||
ListenSshConnectionResponse(QObject *sender, ConnectionSettings* settings) :
|
||||
ListenSshConnectionResponse(QObject *sender, int serverHandle, ConnectionSettings* settings, ConnectionType connectionType) :
|
||||
Event(sender),
|
||||
settings(settings) {}
|
||||
settings(settings),
|
||||
serverHandle(serverHandle),
|
||||
connectionType(connectionType) {}
|
||||
|
||||
ListenSshConnectionResponse(QObject *sender, const EventError &error, ConnectionSettings* settings) :
|
||||
ListenSshConnectionResponse(QObject *sender, const EventError &error, int serverHandle, ConnectionSettings* settings, ConnectionType connectionType) :
|
||||
Event(sender, error),
|
||||
settings(settings) {}
|
||||
settings(settings),
|
||||
serverHandle(serverHandle),
|
||||
connectionType(connectionType) {}
|
||||
|
||||
ConnectionSettings* settings;
|
||||
ConnectionType connectionType;
|
||||
int serverHandle;
|
||||
};
|
||||
|
||||
class LogEvent : public Event
|
||||
@@ -1062,10 +1105,10 @@ namespace Robomongo
|
||||
R_EVENT
|
||||
|
||||
enum LogLevel {
|
||||
ERROR = 1,
|
||||
WARN = 2,
|
||||
INFO = 3,
|
||||
DEBUG = 100 // log as much as possible
|
||||
RBM_ERROR = 1,
|
||||
RBM_WARN = 2,
|
||||
RBM_INFO = 3,
|
||||
RBM_DEBUG = 100 // log as much as possible
|
||||
};
|
||||
|
||||
LogEvent(QObject *sender, const std::string& message, LogLevel level) :
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace
|
||||
using namespace Robomongo::BsonUtils;
|
||||
Robomongo::EnsureIndexInfo info(collection);
|
||||
info._name = getField<mongo::String>(obj, "name");
|
||||
mongo::BSONObj keyObj = getField<mongo::Object>(obj,"key");
|
||||
mongo::BSONObj keyObj = getField<mongo::Object>(obj, "key");
|
||||
if (keyObj.isValid()) {
|
||||
info._request = jsonString(keyObj, mongo::TenGen, 1, Robomongo::DefaultEncoding, Robomongo::Utc);
|
||||
}
|
||||
@@ -56,7 +56,7 @@ namespace Robomongo
|
||||
float result = 0.0f;
|
||||
mongo::BSONObj resultObj;
|
||||
_dbclient->runCommand("db", BSON("buildInfo" << "1"), resultObj);
|
||||
std::string resultStr = BsonUtils::getField<mongo::String>(resultObj,"version");
|
||||
std::string resultStr = BsonUtils::getField<mongo::String>(resultObj, "version");
|
||||
result = atof(resultStr.c_str());
|
||||
return result;
|
||||
}
|
||||
@@ -87,7 +87,7 @@ namespace Robomongo
|
||||
float ver = getVersion();
|
||||
while (cursor->more()) {
|
||||
mongo::BSONObj bsonObj = cursor->next();
|
||||
MongoUser user(ver,bsonObj);
|
||||
MongoUser user(ver, bsonObj);
|
||||
users.push_back(user);
|
||||
}
|
||||
|
||||
@@ -157,13 +157,13 @@ namespace Robomongo
|
||||
|
||||
for (std::list<mongo::BSONObj>::iterator it = indexes.begin(); it != indexes.end(); ++it) {
|
||||
mongo::BSONObj bsonObj = *it;
|
||||
result.push_back(makeEnsureIndexInfoFromBsonObj(collection,bsonObj));
|
||||
result.push_back(makeEnsureIndexInfoFromBsonObj(collection, bsonObj));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MongoClient::ensureIndex(const EnsureIndexInfo &oldInfo,const EnsureIndexInfo &newInfo) const
|
||||
void MongoClient::ensureIndex(const EnsureIndexInfo &oldInfo, const EnsureIndexInfo &newInfo) const
|
||||
{
|
||||
std::string ns = newInfo._collection.ns().toString();
|
||||
|
||||
@@ -172,8 +172,8 @@ namespace Robomongo
|
||||
|
||||
mongo::BSONObj keys = mongo::Robomongo::fromjson(newInfo._request);
|
||||
mongo::BSONObjBuilder toSave;
|
||||
bool cache=true;
|
||||
int version =-1;
|
||||
bool cache = true;
|
||||
int version = -1;
|
||||
|
||||
toSave.append( "ns" , ns );
|
||||
toSave.append( "key" , keys );
|
||||
@@ -400,7 +400,7 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
|
||||
void MongoClient::copyCollectionToDiffServer(mongo::DBClientBase *const fromServ,const MongoNamespace &from, const MongoNamespace &to)
|
||||
void MongoClient::copyCollectionToDiffServer(mongo::DBClientBase *const fromServ, const MongoNamespace &from, const MongoNamespace &to)
|
||||
{
|
||||
if (!_dbclient->exists(to.toString()))
|
||||
_dbclient->createCollection(to.toString());
|
||||
@@ -497,9 +497,9 @@ namespace Robomongo
|
||||
std::vector<MongoCollectionInfo> MongoClient::runCollStatsCommand(const std::vector<std::string> &namespaces)
|
||||
{
|
||||
std::vector<MongoCollectionInfo> infos;
|
||||
for (std::vector<std::string>::const_iterator it = namespaces.begin(); it!=namespaces.end(); ++it) {
|
||||
for (std::vector<std::string>::const_iterator it = namespaces.begin(); it != namespaces.end(); ++it) {
|
||||
MongoCollectionInfo info = runCollStatsCommand(*it);
|
||||
if (info.ns().isValid()){
|
||||
if (info.ns().isValid()) {
|
||||
infos.push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Robomongo
|
||||
void renameCollection(const MongoNamespace &ns, const std::string &newCollectionName);
|
||||
void duplicateCollection(const MongoNamespace &ns, const std::string &newCollectionName);
|
||||
void dropCollection(const MongoNamespace &ns);
|
||||
void copyCollectionToDiffServer(mongo::DBClientBase *const,const MongoNamespace &from, const MongoNamespace &to);
|
||||
void copyCollectionToDiffServer(mongo::DBClientBase *const, const MongoNamespace &from, const MongoNamespace &to);
|
||||
|
||||
void insertDocument(const mongo::BSONObj &obj, const MongoNamespace &ns);
|
||||
void saveDocument(const mongo::BSONObj &obj, const MongoNamespace &ns);
|
||||
|
||||
@@ -17,7 +17,8 @@
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
MongoWorker::MongoWorker(ConnectionSettings *connection, bool isLoadMongoRcJs, int batchSize, QObject *parent) : QObject(parent),
|
||||
MongoWorker::MongoWorker(ConnectionSettings *connection, bool isLoadMongoRcJs, int batchSize,
|
||||
int mongoTimeoutSec, int shellTimeoutSec, QObject *parent) : QObject(parent),
|
||||
_connection(connection),
|
||||
_scriptEngine(NULL),
|
||||
_dbclient(NULL),
|
||||
@@ -25,11 +26,13 @@ namespace Robomongo
|
||||
_isLoadMongoRcJs(isLoadMongoRcJs),
|
||||
_batchSize(batchSize),
|
||||
_timerId(-1),
|
||||
_dbAutocompleteCacheTimerId(-1),
|
||||
_mongoTimeoutSec(mongoTimeoutSec),
|
||||
_shellTimeoutSec(shellTimeoutSec),
|
||||
_isQuiting(0)
|
||||
{
|
||||
{
|
||||
_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();
|
||||
@@ -39,6 +42,13 @@ namespace Robomongo
|
||||
{
|
||||
if (_timerId == event->timerId()) {
|
||||
keepAlive();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_dbAutocompleteCacheTimerId == event->timerId() &&
|
||||
_scriptEngine != NULL) {
|
||||
_scriptEngine->invalidateDbCollectionsCache();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,11 +80,12 @@ namespace Robomongo
|
||||
void MongoWorker::init()
|
||||
{
|
||||
try {
|
||||
_scriptEngine = new ScriptEngine(_connection);
|
||||
_scriptEngine = new ScriptEngine(_connection, _shellTimeoutSec);
|
||||
_scriptEngine->init(_isLoadMongoRcJs);
|
||||
_scriptEngine->use(_connection->defaultDatabase());
|
||||
_scriptEngine->setBatchSize(_batchSize);
|
||||
_timerId = startTimer(pingTimeMs);
|
||||
_dbAutocompleteCacheTimerId = startTimer(30000);
|
||||
} catch (const std::exception &ex) {
|
||||
LOG_MSG(ex.what(), mongo::logger::LogSeverity::Error());
|
||||
}
|
||||
@@ -93,7 +104,12 @@ namespace Robomongo
|
||||
|
||||
MongoWorker::~MongoWorker()
|
||||
{
|
||||
killTimer(_timerId);
|
||||
if (_timerId != -1)
|
||||
killTimer(_timerId);
|
||||
|
||||
if (_dbAutocompleteCacheTimerId != -1)
|
||||
killTimer(_dbAutocompleteCacheTimerId);
|
||||
|
||||
delete _dbclient;
|
||||
delete _connection;
|
||||
delete _scriptEngine;
|
||||
@@ -116,9 +132,15 @@ namespace Robomongo
|
||||
QMutexLocker lock(&_firstConnectionMutex);
|
||||
|
||||
try {
|
||||
mongo::DBClientBase *conn = getConnection();
|
||||
bool hasPrimary = _connection->hasEnabledPrimaryCredential();
|
||||
if (hasPrimary) {
|
||||
mongo::DBClientBase *conn = getConnection(true);
|
||||
if (conn == NULL) {
|
||||
reply(event->sender(), new EstablishConnectionResponse(this,
|
||||
EventError("Network is unreachable"), event->connectionType,
|
||||
EstablishConnectionResponse::MongoConnection));
|
||||
return;
|
||||
}
|
||||
|
||||
if (_connection->hasEnabledPrimaryCredential()) {
|
||||
CredentialSettings *credentials = _connection->primaryCredential();
|
||||
|
||||
// Building BSON object:
|
||||
@@ -138,21 +160,28 @@ namespace Robomongo
|
||||
if (dbName.compare("admin") != 0) // dbName is NOT "admin"
|
||||
_isAdmin = false;
|
||||
}
|
||||
|
||||
boost::scoped_ptr<MongoClient> client(getClient());
|
||||
std::vector<std::string> dbNames = getDatabaseNamesSafe();
|
||||
reply(event->sender(), new EstablishConnectionResponse(this, ConnectionInfo(_connection->getFullAddress(), dbNames, client->getVersion()) ));
|
||||
|
||||
// If we do not have databases, it means that we are unable to
|
||||
// execute "listdatabases" command and we have nothing to show.
|
||||
if (dbNames.size() == 0)
|
||||
throw mongo::DBException("Failed to execute \"listdatabases\" command.", 0);
|
||||
|
||||
init();
|
||||
|
||||
reply(event->sender(), new EstablishConnectionResponse(this, ConnectionInfo(_connection->getFullAddress(), dbNames, client->getVersion()), event->connectionType));
|
||||
} catch(const std::exception &ex) {
|
||||
reply(event->sender(), new EstablishConnectionResponse(this, EventError(ex.what())));
|
||||
LOG_MSG(ex.what(), mongo::logger::LogSeverity::Error());
|
||||
reply(event->sender(), new EstablishConnectionResponse(this, EventError(ex.what()), event->connectionType, EstablishConnectionResponse::MongoAuth));
|
||||
}
|
||||
}
|
||||
|
||||
std::string MongoWorker::getAuthBase() const
|
||||
{
|
||||
bool hasPrimary = _connection->hasEnabledPrimaryCredential();
|
||||
if(hasPrimary){
|
||||
if (_connection->hasEnabledPrimaryCredential())
|
||||
return _connection->primaryCredential()->databaseName();
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
@@ -168,10 +197,9 @@ namespace Robomongo
|
||||
try {
|
||||
boost::scoped_ptr<MongoClient> client(getClient());
|
||||
result = client->getDatabaseNames();
|
||||
} catch(const std::exception &ex) {
|
||||
} catch(const std::exception &) {
|
||||
if (!authBase.empty())
|
||||
result.push_back(authBase);
|
||||
LOG_MSG(ex.what(), mongo::logger::LogSeverity::Error());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -202,7 +230,7 @@ namespace Robomongo
|
||||
if (dbNames.size()) {
|
||||
reply(event->sender(), new LoadDatabaseNamesResponse(this, dbNames));
|
||||
} else {
|
||||
reply(event->sender(), new LoadDatabaseNamesResponse(this, EventError("Unable to load database names.")));
|
||||
reply(event->sender(), new LoadDatabaseNamesResponse(this, EventError("Failed to execute \"listdatabases\" command.")));
|
||||
}
|
||||
} catch(const mongo::DBException &ex) {
|
||||
reply(event->sender(), new LoadDatabaseNamesResponse(this, EventError(ex.what())));
|
||||
@@ -263,7 +291,7 @@ namespace Robomongo
|
||||
const EnsureIndexInfo &oldInfo = event->oldInfo();
|
||||
try {
|
||||
boost::scoped_ptr<MongoClient> client(getClient());
|
||||
client->ensureIndex(oldInfo,newInfo);
|
||||
client->ensureIndex(oldInfo, newInfo);
|
||||
const std::vector<EnsureIndexInfo> &ind = client->getIndexes(newInfo._collection);
|
||||
client->done();
|
||||
|
||||
@@ -278,7 +306,7 @@ namespace Robomongo
|
||||
{
|
||||
try {
|
||||
boost::scoped_ptr<MongoClient> client(getClient());
|
||||
client->dropIndexFromCollection(event->collection(),event->name());
|
||||
client->dropIndexFromCollection(event->collection(), event->name());
|
||||
client->done();
|
||||
reply(event->sender(), new DeleteCollectionIndexResponse(this, event->collection(), event->name()));
|
||||
} catch(const mongo::DBException &ex) {
|
||||
@@ -291,7 +319,7 @@ namespace Robomongo
|
||||
{
|
||||
try {
|
||||
boost::scoped_ptr<MongoClient> client(getClient());
|
||||
client->renameIndexFromCollection(event->collection(),event->oldIndex(),event->newIndex());
|
||||
client->renameIndexFromCollection(event->collection(), event->oldIndex(), event->newIndex());
|
||||
const std::vector<EnsureIndexInfo> &ind = client->getIndexes(event->collection());
|
||||
client->done();
|
||||
|
||||
@@ -372,6 +400,11 @@ namespace Robomongo
|
||||
void MongoWorker::handle(ExecuteScriptRequest *event)
|
||||
{
|
||||
try {
|
||||
if (!_scriptEngine) {
|
||||
reply(event->sender(), new ExecuteScriptResponse(this, EventError("MongoDB Shell was not initialized")));
|
||||
return;
|
||||
}
|
||||
|
||||
MongoShellExecResult result = _scriptEngine->exec(event->script, event->databaseName);
|
||||
reply(event->sender(), new ExecuteScriptResponse(this, result, event->script.empty()));
|
||||
} catch(const mongo::DBException &ex) {
|
||||
@@ -386,6 +419,10 @@ namespace Robomongo
|
||||
void MongoWorker::handle(StopScriptRequest *)
|
||||
{
|
||||
try {
|
||||
if (!_scriptEngine) {
|
||||
return;
|
||||
}
|
||||
|
||||
_scriptEngine->interrupt();
|
||||
} catch(const mongo::DBException &ex) {
|
||||
LOG_MSG(ex.what(), mongo::logger::LogSeverity::Error());
|
||||
@@ -395,6 +432,11 @@ namespace Robomongo
|
||||
void MongoWorker::handle(AutocompleteRequest *event)
|
||||
{
|
||||
try {
|
||||
if (!_scriptEngine) {
|
||||
reply(event->sender(), new AutocompleteResponse(this, EventError("MongoDB Shell was not initialized")));
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList list = _scriptEngine->complete(event->prefix, event->mode);
|
||||
reply(event->sender(), new AutocompleteResponse(this, list, event->prefix));
|
||||
} catch(const mongo::DBException &ex) {
|
||||
@@ -498,7 +540,7 @@ namespace Robomongo
|
||||
try {
|
||||
boost::scoped_ptr<MongoClient> client(getClient());
|
||||
MongoWorker *cl = event->worker();
|
||||
client->copyCollectionToDiffServer(cl->_dbclient,event->from(),event->to());
|
||||
client->copyCollectionToDiffServer(cl->_dbclient, event->from(), event->to());
|
||||
client->done();
|
||||
|
||||
reply(event->sender(), new CopyCollectionToDiffServerResponse(this));
|
||||
@@ -564,13 +606,19 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
|
||||
mongo::DBClientBase *MongoWorker::getConnection()
|
||||
mongo::DBClientBase *MongoWorker::getConnection(bool mayReturnNull /* = false */)
|
||||
{
|
||||
if (!_dbclient) {
|
||||
// Timeout for operations is 10 seconds.
|
||||
// Timeout for operations
|
||||
// Connect timeout is fixed, but short, at 5 seconds (see headers for DBClientConnection)
|
||||
mongo::DBClientConnection *conn = new mongo::DBClientConnection(true, 10);
|
||||
conn->connect(_connection->info());
|
||||
mongo::DBClientConnection *conn = new mongo::DBClientConnection(true, _mongoTimeoutSec);
|
||||
mongo::Status status = conn->connect(_connection->info());
|
||||
|
||||
if (!status.isOK() && mayReturnNull) {
|
||||
delete conn;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_dbclient = conn;
|
||||
}
|
||||
return _dbclient;
|
||||
|
||||
@@ -23,7 +23,8 @@ namespace Robomongo
|
||||
|
||||
public:
|
||||
typedef std::vector<std::string> DatabasesContainerType;
|
||||
explicit MongoWorker(ConnectionSettings *connection, bool isLoadMongoRcJs, int batchSize, QObject *parent = NULL);
|
||||
explicit MongoWorker(ConnectionSettings *connection, bool isLoadMongoRcJs, int batchSize,
|
||||
int mongoTimeoutSec, int shellTimeoutSec, QObject *parent = NULL);
|
||||
~MongoWorker();
|
||||
enum { pingTimeMs = 60 * 1000 };
|
||||
void interrupt();
|
||||
@@ -131,7 +132,7 @@ namespace Robomongo
|
||||
std::string getAuthBase() const;
|
||||
|
||||
mongo::DBClientBase *_dbclient;
|
||||
mongo::DBClientBase *getConnection();
|
||||
mongo::DBClientBase *getConnection(bool mayReturnNull = false);
|
||||
MongoClient *getClient();
|
||||
|
||||
/**
|
||||
@@ -147,13 +148,16 @@ namespace Robomongo
|
||||
const bool _isLoadMongoRcJs;
|
||||
const int _batchSize;
|
||||
int _timerId;
|
||||
int _dbAutocompleteCacheTimerId;
|
||||
int _mongoTimeoutSec;
|
||||
int _shellTimeoutSec;
|
||||
QAtomicInteger<int> _isQuiting;
|
||||
|
||||
ConnectionSettings *_connection;
|
||||
|
||||
// Collection of created databases.
|
||||
// Starting from 3.0, MongoDB drops empty databases.
|
||||
// It means, we do not find a way to create "empty" database.
|
||||
// It means, we did not find a way to create "empty" database.
|
||||
// We save all created databases in this collection and merge with
|
||||
// list of real databases returned from MongoDB server.
|
||||
std::unordered_set<std::string> _createdDbs;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "robomongo/core/mongodb/SshTunnelWorker.h"
|
||||
|
||||
#include <QThread>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include "robomongo/core/utils/QtUtils.h"
|
||||
#include "robomongo/core/utils/Logger.h"
|
||||
#include "robomongo/core/settings/ConnectionSettings.h"
|
||||
@@ -15,50 +17,23 @@ namespace Robomongo
|
||||
{
|
||||
SshTunnelWorker::SshTunnelWorker(ConnectionSettings *settings) : QObject(),
|
||||
_settings(settings),
|
||||
_sshConfig(NULL),
|
||||
_sshSession(NULL)
|
||||
_sshSession(NULL),
|
||||
_configCreator(settings)
|
||||
{
|
||||
_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();
|
||||
}
|
||||
|
||||
void SshTunnelWorker::init()
|
||||
{
|
||||
try {
|
||||
SshSettings *ssh = _settings->sshSettings();
|
||||
|
||||
// We are going to access raw char* buffers, so prepare copies
|
||||
// of strings (and rest of the things for symmetry)
|
||||
_sshhost = ssh->host();
|
||||
_sshport = ssh->port();
|
||||
_remotehost = _settings->serverHost();
|
||||
_remoteport = _settings->serverPort();
|
||||
_localip = "127.0.0.1";
|
||||
_localport = 27040;
|
||||
|
||||
_userName = ssh->userName();
|
||||
_userPassword = ssh->userPassword();
|
||||
_privateKeyFile = ssh->privateKeyFile();
|
||||
_publicKeyFile = ssh->publicKeyFile();
|
||||
_passphrase = ssh->passphrase();
|
||||
_authMethod = ssh->authMethod(); // "password" or "publickey"
|
||||
}
|
||||
catch (const std::exception &ex) {
|
||||
LOG_MSG(ex.what(), mongo::logger::LogSeverity::Error());
|
||||
}
|
||||
}
|
||||
|
||||
SshTunnelWorker::~SshTunnelWorker()
|
||||
{
|
||||
// QThread "_thread" and MongoWorker itself will be deleted later
|
||||
// (see MongoWorker() constructor)
|
||||
|
||||
delete _settings;
|
||||
delete _sshConfig;
|
||||
printf("SSH tunnel closed.\n");
|
||||
}
|
||||
|
||||
void SshTunnelWorker::stopAndDelete() {
|
||||
@@ -71,30 +46,12 @@ namespace Robomongo
|
||||
if (_isQuiting)
|
||||
return;
|
||||
|
||||
_sshConfig = new rbm_ssh_tunnel_config;
|
||||
_sshConfig->sshserverip = const_cast<char*>(_sshhost.c_str());
|
||||
_sshConfig->sshserverport = static_cast<unsigned int>(_sshport);
|
||||
_sshConfig->remotehost = const_cast<char*>(_remotehost.c_str());
|
||||
_sshConfig->remoteport = static_cast<unsigned int>(_remoteport);
|
||||
_sshConfig->localip = const_cast<char*>(_localip.c_str());
|
||||
_sshConfig->localport = static_cast<unsigned int>(_localport);
|
||||
|
||||
_sshConfig->username = const_cast<char*>(_userName.c_str());
|
||||
_sshConfig->password = const_cast<char*>(_userPassword.c_str());
|
||||
_sshConfig->privatekeyfile = const_cast<char*>(_privateKeyFile.c_str());
|
||||
_sshConfig->publickeyfile = _publicKeyFile.empty() ? NULL : const_cast<char*>(_publicKeyFile.c_str());
|
||||
_sshConfig->passphrase = const_cast<char*>(_passphrase.c_str());
|
||||
_sshConfig->authtype = (_authMethod == "publickey") ? RBM_SSH_AUTH_TYPE_PUBLICKEY : RBM_SSH_AUTH_TYPE_PASSWORD;
|
||||
|
||||
_sshConfig->logcontext = this;
|
||||
_sshConfig->logcallback = &SshTunnelWorker::logCallbackHandler;
|
||||
_sshConfig->loglevel = (rbm_ssh_log_type) _settings->sshSettings()->logLevel(); // RBM_SSH_LOG_TYPE_DEBUG;
|
||||
|
||||
if ((_sshSession = rbm_ssh_session_create(_sshConfig)) == 0) {
|
||||
// Cleanup config structure
|
||||
delete _sshConfig;
|
||||
_sshConfig = NULL;
|
||||
// Additionally configure "rbm_ssh_tunnel_config"
|
||||
_configCreator.config()->logcontext = this;
|
||||
_configCreator.config()->logcallback = &SshTunnelWorker::logCallbackHandler;
|
||||
_configCreator.config()->loglevel = (rbm_ssh_log_type) _settings->sshSettings()->logLevel(); // RBM_SSH_LOG_TYPE_DEBUG;
|
||||
|
||||
if ((_sshSession = rbm_ssh_session_create(_configCreator.config())) == 0) {
|
||||
// Not much we can say about this error
|
||||
throw std::runtime_error("Failed to create SSH session");
|
||||
}
|
||||
@@ -113,20 +70,16 @@ namespace Robomongo
|
||||
rbm_ssh_session_close(_sshSession);
|
||||
_sshSession = NULL;
|
||||
|
||||
// Cleanup config
|
||||
delete _sshConfig;
|
||||
_sshConfig = NULL;
|
||||
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
reply(event->sender(), new EstablishSshConnectionResponse(
|
||||
this, event->worker, event->settings, event->visible, _sshConfig->localport));
|
||||
this, event->serverHandle, event->worker, event->settings, event->connectionType, _configCreator.config()->localport));
|
||||
|
||||
} catch (const std::exception& ex) {
|
||||
reply(event->sender(),
|
||||
new EstablishSshConnectionResponse(this, EventError(ex.what()),
|
||||
event->worker, event->settings, event->visible));
|
||||
new EstablishSshConnectionResponse(this, event->serverHandle, EventError(ex.what()),
|
||||
event->worker, event->settings, event->connectionType));
|
||||
|
||||
// In case of error in connection, we should cleanup SshTunnelWorker
|
||||
stopAndDelete();
|
||||
@@ -134,28 +87,50 @@ namespace Robomongo
|
||||
}
|
||||
|
||||
void SshTunnelWorker::handle(ListenSshConnectionRequest *event) {
|
||||
|
||||
// do it here, i.e. cycle
|
||||
|
||||
try {
|
||||
if (_isQuiting)
|
||||
return;
|
||||
|
||||
if (_sshSession == NULL || _sshConfig == NULL)
|
||||
if (_sshSession == NULL)
|
||||
return;
|
||||
|
||||
// We are running this timer in order to distinguish between two
|
||||
// types of errors:
|
||||
// 1) SSH tunnel wasn't successfully created
|
||||
// 2) SSH tunnel was disconnected
|
||||
// This is used now only for UI error message, that we show to user.
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
// This function will block until all TCP connections disconnects.
|
||||
// Initially, it will wait for at least one such connection.
|
||||
if (rbm_ssh_open_tunnel(_sshSession) != 0) {
|
||||
|
||||
qint64 elapsed = timer.elapsed();
|
||||
bool wasDisconnected = elapsed > 20000; // More than 20 seconds passed
|
||||
|
||||
// Prepare copy of error message (if any)
|
||||
std::string error(_sshSession->lasterror);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "You are disconnected from SSH tunnel ("
|
||||
<< _settings->sshSettings()->host() << ":"
|
||||
<< _settings->sshSettings()->port() << "). "
|
||||
<< "Please initiate a new connection and reopen all tabs.\n\nError:\n"
|
||||
<< error;
|
||||
|
||||
if (wasDisconnected) {
|
||||
ss << "You are disconnected from SSH tunnel ("
|
||||
<< _settings->sshSettings()->host() << ":"
|
||||
<< _settings->sshSettings()->port() << "). "
|
||||
<< "Please initiate a new connection and reopen all tabs.\n\nError:\n"
|
||||
<< error;
|
||||
} else {
|
||||
ss << "Cannot establish SSH tunnel ("
|
||||
<< _settings->sshSettings()->host() << ":"
|
||||
<< _settings->sshSettings()->port() << "). "
|
||||
<< "\n\nError:\n"
|
||||
<< error;
|
||||
}
|
||||
|
||||
// Cleanup session
|
||||
rbm_ssh_session_close(_sshSession);
|
||||
_sshSession = NULL;
|
||||
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
@@ -164,7 +139,7 @@ namespace Robomongo
|
||||
|
||||
} catch (const std::exception& ex) {
|
||||
reply(event->sender(),
|
||||
new ListenSshConnectionResponse(this, EventError(ex.what()), _settings));
|
||||
new ListenSshConnectionResponse(this, EventError(ex.what()), event->serverHandle, _settings, event->connectionType));
|
||||
}
|
||||
|
||||
// When we done with SSH (i.e. rbm_ssh_open_tunnel exits) regardless
|
||||
@@ -195,4 +170,60 @@ namespace Robomongo
|
||||
void SshTunnelWorker::logCallbackHandler(void *context, char *message, int level) {
|
||||
static_cast<SshTunnelWorker*>(context)->log(message, level);
|
||||
}
|
||||
|
||||
/*
|
||||
* SshTunnelConfigCreator
|
||||
*/
|
||||
SshTunnelConfigCreator::SshTunnelConfigCreator(ConnectionSettings *settings) {
|
||||
SshSettings *ssh = settings->sshSettings();
|
||||
|
||||
// We are going to access raw char* buffers, so prepare copies
|
||||
// of strings (and rest of the things for symmetry)
|
||||
_sshhost = ssh->host();
|
||||
_sshport = ssh->port();
|
||||
_remotehost = settings->serverHost();
|
||||
_remoteport = settings->serverPort();
|
||||
_localip = "127.0.0.1";
|
||||
_localport = 27040;
|
||||
|
||||
_userName = ssh->userName();
|
||||
_userPassword = ssh->userPassword();
|
||||
_privateKeyFile = ssh->privateKeyFile();
|
||||
_publicKeyFile = ssh->publicKeyFile();
|
||||
_passphrase = ssh->passphrase();
|
||||
_authMethod = ssh->authMethod(); // "password" or "publickey"
|
||||
|
||||
// Use "askedPassword" for both passphrase and password if required
|
||||
if (ssh->askPassword()) {
|
||||
_passphrase = ssh->askedPassword();
|
||||
_userPassword = ssh->askedPassword();
|
||||
}
|
||||
|
||||
_sshConfig = new rbm_ssh_tunnel_config;
|
||||
_sshConfig->sshserverhost = const_cast<char*>(_sshhost.c_str());
|
||||
_sshConfig->sshserverport = static_cast<unsigned int>(_sshport);
|
||||
_sshConfig->remotehost = const_cast<char*>(_remotehost.c_str());
|
||||
_sshConfig->remoteport = static_cast<unsigned int>(_remoteport);
|
||||
_sshConfig->localip = const_cast<char*>(_localip.c_str());
|
||||
_sshConfig->localport = static_cast<unsigned int>(_localport);
|
||||
|
||||
_sshConfig->username = const_cast<char*>(_userName.c_str());
|
||||
_sshConfig->password = const_cast<char*>(_userPassword.c_str());
|
||||
_sshConfig->privatekeyfile = const_cast<char*>(_privateKeyFile.c_str());
|
||||
_sshConfig->publickeyfile = _publicKeyFile.empty() ? NULL : const_cast<char*>(_publicKeyFile.c_str());
|
||||
_sshConfig->passphrase = const_cast<char*>(_passphrase.c_str());
|
||||
_sshConfig->authtype = (_authMethod == "publickey") ? RBM_SSH_AUTH_TYPE_PUBLICKEY : RBM_SSH_AUTH_TYPE_PASSWORD;
|
||||
|
||||
// Default settings
|
||||
_sshConfig->logcontext = NULL;
|
||||
_sshConfig->logcallback = NULL;
|
||||
_sshConfig->loglevel = RBM_SSH_LOG_TYPE_ERROR;
|
||||
|
||||
}
|
||||
|
||||
SshTunnelConfigCreator::~SshTunnelConfigCreator() {
|
||||
delete _sshConfig;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <robomongo/ssh/ssh.h>
|
||||
#include "robomongo/core/events/MongoEvents.h"
|
||||
|
||||
@@ -17,6 +18,34 @@ namespace Robomongo
|
||||
class EstablishSshConnectionRequest;
|
||||
class ListenSshConnectionRequest;
|
||||
|
||||
/*
|
||||
* Helper class for creating rbm_ssh_tunnel_config from ConnectionSettings
|
||||
* Automatically deletes allocated structure
|
||||
*/
|
||||
class SshTunnelConfigCreator {
|
||||
public:
|
||||
explicit SshTunnelConfigCreator(ConnectionSettings *settings);
|
||||
~SshTunnelConfigCreator();
|
||||
rbm_ssh_tunnel_config *config() { return _sshConfig; }
|
||||
|
||||
private:
|
||||
std::string _sshhost;
|
||||
int _sshport;
|
||||
std::string _remotehost;
|
||||
int _remoteport;
|
||||
std::string _localip;
|
||||
int _localport;
|
||||
|
||||
std::string _userName;
|
||||
std::string _userPassword;
|
||||
std::string _privateKeyFile;
|
||||
std::string _publicKeyFile;
|
||||
std::string _passphrase;
|
||||
std::string _authMethod; // "password" or "publickey"
|
||||
|
||||
rbm_ssh_tunnel_config* _sshConfig;
|
||||
};
|
||||
|
||||
class SshTunnelWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -31,7 +60,6 @@ namespace Robomongo
|
||||
void stopAndDelete();
|
||||
|
||||
protected Q_SLOTS: // handlers:
|
||||
void init();
|
||||
void handle(EstablishSshConnectionRequest *event);
|
||||
void handle(ListenSshConnectionRequest *event);
|
||||
|
||||
@@ -42,21 +70,9 @@ namespace Robomongo
|
||||
QThread *_thread;
|
||||
QAtomicInteger<int> _isQuiting;
|
||||
ConnectionSettings* _settings;
|
||||
rbm_ssh_tunnel_config* _sshConfig;
|
||||
rbm_ssh_session* _sshSession;
|
||||
|
||||
std::string _sshhost;
|
||||
int _sshport;
|
||||
std::string _remotehost;
|
||||
int _remoteport;
|
||||
std::string _localip;
|
||||
int _localport;
|
||||
|
||||
std::string _userName;
|
||||
std::string _userPassword;
|
||||
std::string _privateKeyFile;
|
||||
std::string _publicKeyFile;
|
||||
std::string _passphrase;
|
||||
std::string _authMethod; // "password" or "publickey"
|
||||
SshTunnelConfigCreator _configCreator;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace
|
||||
const unsigned port = 27017;
|
||||
const char *defaultServerHost = "localhost";
|
||||
const char *defaultNameConnection = "New Connection";
|
||||
|
||||
const int maxLength = 300;
|
||||
}
|
||||
|
||||
namespace Robomongo
|
||||
@@ -27,12 +29,12 @@ namespace Robomongo
|
||||
|
||||
void ConnectionSettings::fromVariant(const QVariantMap &map) {
|
||||
setConnectionName(QtUtils::toStdString(map.value("connectionName").toString()));
|
||||
setServerHost(QtUtils::toStdString(map.value("serverHost").toString()));
|
||||
setServerHost(QtUtils::toStdString(map.value("serverHost").toString().left(maxLength)));
|
||||
setServerPort(map.value("serverPort").toInt());
|
||||
setDefaultDatabase(QtUtils::toStdString(map.value("defaultDatabase").toString()));
|
||||
|
||||
QVariantList list = map.value("credentials").toList();
|
||||
for(QVariantList::const_iterator it = list.begin(); it != list.end(); ++it) {
|
||||
for (QVariantList::const_iterator it = list.begin(); it != list.end(); ++it) {
|
||||
QVariant var = *it;
|
||||
CredentialSettings *credential = new CredentialSettings(var.toMap());
|
||||
addCredential(credential);
|
||||
@@ -106,7 +108,7 @@ namespace Robomongo
|
||||
map.insert("sslPemKeyFile", QtUtils::toQString(infl._sslPEMKeyFile));
|
||||
#endif
|
||||
QVariantList list;
|
||||
for(QList<CredentialSettings *>::const_iterator it = _credentials.begin(); it != _credentials.end(); ++it) {
|
||||
for (QList<CredentialSettings *>::const_iterator it = _credentials.begin(); it != _credentials.end(); ++it) {
|
||||
CredentialSettings *credential = *it;
|
||||
list.append(credential->toVariant());
|
||||
}
|
||||
@@ -120,7 +122,7 @@ namespace Robomongo
|
||||
CredentialSettings *ConnectionSettings::findCredential(const std::string &databaseName) const
|
||||
{
|
||||
CredentialSettings *result = NULL;
|
||||
for(QList<CredentialSettings *>::const_iterator it = _credentials.begin(); it != _credentials.end(); ++it) {
|
||||
for (QList<CredentialSettings *>::const_iterator it = _credentials.begin(); it != _credentials.end(); ++it) {
|
||||
CredentialSettings *cred = *it;
|
||||
if (cred->databaseName() == databaseName) {
|
||||
result = cred;
|
||||
|
||||
@@ -48,7 +48,9 @@ namespace Robomongo
|
||||
_textFontFamily(""),
|
||||
_textFontPointSize(-1),
|
||||
_lineNumbers(false),
|
||||
_loadMongoRcJs(false)
|
||||
_loadMongoRcJs(false),
|
||||
_mongoTimeoutSec(10),
|
||||
_shellTimeoutSec(15)
|
||||
{
|
||||
load();
|
||||
LOG_MSG("SettingsManager initialized in " + _configPath, mongo::logger::LogSeverity::Info(), false);
|
||||
@@ -56,7 +58,7 @@ namespace Robomongo
|
||||
|
||||
SettingsManager::~SettingsManager()
|
||||
{
|
||||
std::for_each(_connections.begin() ,_connections.end(), stdutils::default_delete<ConnectionSettings *>());
|
||||
std::for_each(_connections.begin(), _connections.end(), stdutils::default_delete<ConnectionSettings *>());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,6 +181,14 @@ namespace Robomongo
|
||||
_textFontFamily = map.value("textFontFamily").toString();
|
||||
_textFontPointSize = map.value("textFontPointSize").toInt();
|
||||
|
||||
if (map.contains("mongoTimeoutSec")) {
|
||||
_mongoTimeoutSec = map.value("mongoTimeoutSec").toInt();
|
||||
}
|
||||
|
||||
if (map.contains("shellTimeoutSec")) {
|
||||
_shellTimeoutSec = map.value("shellTimeoutSec").toInt();
|
||||
}
|
||||
|
||||
// 5. Load connections
|
||||
_connections.clear();
|
||||
|
||||
@@ -239,6 +249,8 @@ namespace Robomongo
|
||||
|
||||
// 8. Save batchSize
|
||||
map.insert("batchSize", _batchSize);
|
||||
map.insert("mongoTimeoutSec", _mongoTimeoutSec);
|
||||
map.insert("shellTimeoutSec", _shellTimeoutSec);
|
||||
|
||||
// 9. Save style
|
||||
map.insert("style", _currentStyle);
|
||||
@@ -250,7 +262,7 @@ namespace Robomongo
|
||||
// 11. Save connections
|
||||
QVariantList list;
|
||||
|
||||
for (ConnectionSettingsContainerType::const_iterator it = _connections.begin(); it!=_connections.end(); ++it) {
|
||||
for (ConnectionSettingsContainerType::const_iterator it = _connections.begin(); it != _connections.end(); ++it) {
|
||||
QVariantMap rm = (*it)->toVariant().toMap();
|
||||
list.append(rm);
|
||||
}
|
||||
@@ -277,8 +289,8 @@ namespace Robomongo
|
||||
*/
|
||||
void SettingsManager::removeConnection(ConnectionSettings *connection)
|
||||
{
|
||||
ConnectionSettingsContainerType::iterator it = std::find(_connections.begin(),_connections.end(),connection);
|
||||
if (it!=_connections.end()) {
|
||||
ConnectionSettingsContainerType::iterator it = std::find(_connections.begin(), _connections.end(), connection);
|
||||
if (it != _connections.end()) {
|
||||
_connections.erase(it);
|
||||
delete connection;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace Robomongo
|
||||
UUIDEncoding uuidEncoding() const { return _uuidEncoding; }
|
||||
|
||||
void setTimeZone(SupportedTimes timeZ) { _timeZone = timeZ; }
|
||||
SupportedTimes timeZone() const { return _timeZone;}
|
||||
SupportedTimes timeZone() const { return _timeZone; }
|
||||
|
||||
void setViewMode(ViewMode viewMode) { _viewMode = viewMode; }
|
||||
ViewMode viewMode() const { return _viewMode; }
|
||||
@@ -98,7 +98,7 @@ namespace Robomongo
|
||||
void setBatchSize(int batchSize) { _batchSize = batchSize; }
|
||||
int batchSize() const { return _batchSize; }
|
||||
|
||||
QString currentStyle() const {return _currentStyle; }
|
||||
QString currentStyle() const { return _currentStyle; }
|
||||
void setCurrentStyle(const QString& style);
|
||||
|
||||
QString textFontFamily() const { return _textFontFamily; }
|
||||
@@ -107,6 +107,9 @@ namespace Robomongo
|
||||
int textFontPointSize() const { return _textFontPointSize; }
|
||||
void setTextFontPointSize(int pointSize);
|
||||
|
||||
int mongoTimeoutSec() const { return _mongoTimeoutSec; }
|
||||
int shellTimeoutSec() const { return _shellTimeoutSec; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -125,14 +128,8 @@ namespace Robomongo
|
||||
*/
|
||||
QString _version;
|
||||
|
||||
/**
|
||||
* @brief UUID encoding
|
||||
*/
|
||||
UUIDEncoding _uuidEncoding;
|
||||
SupportedTimes _timeZone;
|
||||
/**
|
||||
* @brief view mode
|
||||
*/
|
||||
ViewMode _viewMode;
|
||||
AutocompletionMode _autocompletionMode;
|
||||
bool _loadMongoRcJs;
|
||||
@@ -144,6 +141,10 @@ namespace Robomongo
|
||||
QString _currentStyle;
|
||||
QString _textFontFamily;
|
||||
int _textFontPointSize;
|
||||
|
||||
int _mongoTimeoutSec;
|
||||
int _shellTimeoutSec;
|
||||
|
||||
/**
|
||||
* @brief List of connections
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,9 @@ namespace Robomongo
|
||||
SshSettings::SshSettings() :
|
||||
_port(22),
|
||||
_authMethod("publickey"),
|
||||
_enabled(false) {
|
||||
_enabled(false),
|
||||
_askPassword(false),
|
||||
_logLevel(1) {
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +29,7 @@ namespace Robomongo
|
||||
map.insert("passphrase", QtUtils::toQString(passphrase()));
|
||||
map.insert("method", QtUtils::toQString(authMethod()));
|
||||
map.insert("enabled", enabled());
|
||||
map.insert("askPassword", askPassword());
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -40,5 +43,6 @@ namespace Robomongo
|
||||
setPassphrase(QtUtils::toStdString(map.value("passphrase").toString()));
|
||||
setAuthMethod(QtUtils::toStdString(map.value("method").toString()));
|
||||
setEnabled(map.value("enabled").toBool());
|
||||
setAskPassword(map.value("askPassword").toBool());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ namespace Robomongo
|
||||
QVariant toVariant() const;
|
||||
void fromVariant(const QVariantMap &map);
|
||||
|
||||
/*
|
||||
* Domain or IPv4 or IPv6 address
|
||||
*/
|
||||
std::string host() const { return _host; }
|
||||
void setHost(const std::string &host) { _host = host; }
|
||||
|
||||
@@ -53,11 +56,17 @@ namespace Robomongo
|
||||
bool enabled() const { return _enabled; }
|
||||
void setEnabled(bool enabled) { _enabled = enabled; }
|
||||
|
||||
bool askPassword() const { return _askPassword; }
|
||||
void setAskPassword(bool ask) { _askPassword = ask; }
|
||||
|
||||
std::string askedPassword() const { return _askedPassword; }
|
||||
void setAskedPassword(const std::string &asked) { _askedPassword = asked; }
|
||||
|
||||
int logLevel() const { return _logLevel; }
|
||||
void setLogLevel(const int logLevel) { _logLevel = logLevel; }
|
||||
|
||||
private:
|
||||
std::string _host;
|
||||
std::string _host; // domain or IPv4/v6
|
||||
int _port;
|
||||
std::string _userName;
|
||||
std::string _userPassword;
|
||||
@@ -66,11 +75,16 @@ namespace Robomongo
|
||||
std::string _passphrase;
|
||||
std::string _authMethod; // "password" or "publickey"
|
||||
|
||||
// Should we ask user about password or passphrase
|
||||
// each time when we try to connect
|
||||
bool _askPassword;
|
||||
|
||||
/**
|
||||
* Flag, indicating whether we should use
|
||||
* this SSH tunnel or not.
|
||||
*/
|
||||
bool _enabled;
|
||||
int _logLevel; // this property is not persisted
|
||||
int _logLevel; // this property is not persisted
|
||||
std::string _askedPassword; // this property is not persisted
|
||||
};
|
||||
}
|
||||
|
||||
@@ -80,23 +80,23 @@ namespace Robomongo
|
||||
s << (isArray ? "[" : "{");
|
||||
BSONObjIterator i(obj);
|
||||
BSONElement e = i.next();
|
||||
if ( !e.eoo() ){
|
||||
if ( !e.eoo() ) {
|
||||
while ( 1 ) {
|
||||
if ( pretty ) {
|
||||
s << '\n';
|
||||
for( int x = 0; x < pretty; x++ ){
|
||||
for( int x = 0; x < pretty; x++ ) {
|
||||
s << " ";
|
||||
}
|
||||
}
|
||||
else {
|
||||
s << " ";
|
||||
}
|
||||
s << jsonString(e, format, true, pretty?pretty+1:0, uuidEncoding, timeFormat, isArray);
|
||||
s << jsonString(e, format, true, pretty ? pretty + 1 : 0, uuidEncoding, timeFormat, isArray);
|
||||
e = i.next();
|
||||
|
||||
if (e.eoo()) {
|
||||
s << '\n';
|
||||
for( int x = 0; x < pretty - 1; x++ ){
|
||||
for( int x = 0; x < pretty - 1; x++ ) {
|
||||
s << " ";
|
||||
}
|
||||
s << (isArray ? "]" : "}");
|
||||
@@ -130,15 +130,21 @@ namespace Robomongo
|
||||
s << "NumberLong(" << elem._numberLong() << ")";
|
||||
break;
|
||||
case NumberInt:
|
||||
s << elem._numberInt();
|
||||
break;
|
||||
case NumberDouble:
|
||||
{
|
||||
int sign=0;
|
||||
int sign = 0;
|
||||
if ( elem.number() >= -std::numeric_limits< double >::max() &&
|
||||
elem.number() <= std::numeric_limits< double >::max() ) {
|
||||
|
||||
// was 16
|
||||
s.precision(std::numeric_limits<double>::digits10);
|
||||
s << elem.number();
|
||||
|
||||
// Leave trailing zero if needed
|
||||
if (elem.number() == (long long)elem.number())
|
||||
s << ".0";
|
||||
}
|
||||
else if (std::isnan(elem.number()) ) {
|
||||
s << "NaN";
|
||||
@@ -166,7 +172,7 @@ namespace Robomongo
|
||||
break;
|
||||
case Object: {
|
||||
BSONObj obj = elem.embeddedObject();
|
||||
s << jsonString(obj, format, pretty, uuidEncoding,timeFormat);
|
||||
s << jsonString(obj, format, pretty, uuidEncoding, timeFormat);
|
||||
}
|
||||
break;
|
||||
case mongo::Array: {
|
||||
@@ -180,7 +186,7 @@ namespace Robomongo
|
||||
if ( !e.eoo() ) {
|
||||
int count = 0;
|
||||
while ( 1 ) {
|
||||
if( pretty ) {
|
||||
if ( pretty ) {
|
||||
s << '\n';
|
||||
for( int x = 0; x < pretty; x++ )
|
||||
s << " ";
|
||||
@@ -190,7 +196,7 @@ namespace Robomongo
|
||||
s << "undefined";
|
||||
}
|
||||
else {
|
||||
s << jsonString(e, format, false, pretty?pretty+1:0, uuidEncoding, timeFormat, true);
|
||||
s << jsonString(e, format, false, pretty ? pretty + 1 : 0, uuidEncoding, timeFormat, true);
|
||||
e = i.next();
|
||||
}
|
||||
count++;
|
||||
@@ -260,13 +266,13 @@ namespace Robomongo
|
||||
case mongo::Date:
|
||||
{
|
||||
Date_t d = elem.date();
|
||||
long long ms = d.toMillisSinceEpoch();//static_cast<long long>(d.millis);
|
||||
long long ms = d.toMillisSinceEpoch(); //static_cast<long long>(d.millis);
|
||||
bool isSupportedDate = miutil::minDate < ms && ms < miutil::maxDate;
|
||||
|
||||
if ( format == Strict )
|
||||
s << "{ \"$date\" : ";
|
||||
else{
|
||||
if(isSupportedDate){
|
||||
if (isSupportedDate) {
|
||||
s << "ISODate(";
|
||||
}
|
||||
else{
|
||||
@@ -275,7 +281,7 @@ namespace Robomongo
|
||||
}
|
||||
|
||||
if ( pretty && isSupportedDate) {
|
||||
boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
|
||||
boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
|
||||
boost::posix_time::time_duration diff = boost::posix_time::millisec(ms);
|
||||
boost::posix_time::ptime time = epoch + diff;
|
||||
std::string timestr = miutil::isotimeString(time, true, timeFormat == LocalTime);
|
||||
@@ -563,13 +569,13 @@ namespace Robomongo
|
||||
con.append(e.fieldName());
|
||||
con.append("\"");
|
||||
con.append(" : ");
|
||||
buildJsonString(e,con,uuid,tz);
|
||||
buildJsonString(e, con, uuid, tz);
|
||||
con.append(", \n");
|
||||
}
|
||||
con.append("\n}\n\n");
|
||||
}
|
||||
|
||||
void buildJsonString(const mongo::BSONElement &elem,std::string &con, UUIDEncoding uuid, SupportedTimes tz)
|
||||
void buildJsonString(const mongo::BSONElement &elem, std::string &con, UUIDEncoding uuid, SupportedTimes tz)
|
||||
{
|
||||
switch (elem.type())
|
||||
{
|
||||
@@ -578,6 +584,11 @@ namespace Robomongo
|
||||
std::stringstream s;
|
||||
s.precision(std::numeric_limits<double>::digits10);
|
||||
s << elem.Double();
|
||||
|
||||
// Leave trailing zero if needed
|
||||
if (elem.Double() == (long long)elem.Double())
|
||||
s << ".0";
|
||||
|
||||
con.append(s.str());
|
||||
}
|
||||
break;
|
||||
@@ -626,13 +637,13 @@ namespace Robomongo
|
||||
long long ms = (long long) elem.Date().toMillisSinceEpoch();
|
||||
bool isSupportedDate = miutil::minDate < ms && ms < miutil::maxDate;
|
||||
|
||||
boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));
|
||||
boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
|
||||
boost::posix_time::time_duration diff = boost::posix_time::millisec(ms);
|
||||
boost::posix_time::ptime time = epoch + diff;
|
||||
|
||||
std::string date;
|
||||
if(isSupportedDate)
|
||||
date = miutil::isotimeString(time,false,tz==LocalTime);
|
||||
if (isSupportedDate)
|
||||
date = miutil::isotimeString(time, false, tz == LocalTime);
|
||||
else
|
||||
date = boost::lexical_cast<std::string>(ms);
|
||||
|
||||
@@ -652,7 +663,7 @@ namespace Robomongo
|
||||
case 'g':
|
||||
case 'i':
|
||||
case 'm':
|
||||
con+=*f;
|
||||
con += *f;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -678,15 +689,15 @@ namespace Robomongo
|
||||
break;
|
||||
case NumberInt:
|
||||
{
|
||||
char num[16]={0};
|
||||
sprintf(num,"%d",elem.Int());
|
||||
char num[16] = {0};
|
||||
sprintf(num, "%d", elem.Int());
|
||||
con.append(num);
|
||||
break;
|
||||
}
|
||||
case bsonTimestamp:
|
||||
{
|
||||
Date_t date = elem.timestampTime();
|
||||
unsigned long long millis = date.toMillisSinceEpoch();// millis;
|
||||
unsigned long long millis = date.toMillisSinceEpoch(); // millis;
|
||||
if ((long long)millis >= 0 &&
|
||||
((long long)millis/1000) < (std::numeric_limits<time_t>::max)()) {
|
||||
con.append(date.toString());
|
||||
@@ -695,8 +706,8 @@ namespace Robomongo
|
||||
}
|
||||
case NumberLong:
|
||||
{
|
||||
char num[32]={0};
|
||||
sprintf(num,"%lld",elem.Long());
|
||||
char num[32] = {0};
|
||||
sprintf(num, "%lld", elem.Long());
|
||||
con.append(num);
|
||||
break;
|
||||
}
|
||||
@@ -706,13 +717,13 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
|
||||
mongo::BSONElement indexOf(const mongo::BSONObj &doc,int index)
|
||||
mongo::BSONElement indexOf(const mongo::BSONObj &doc, int index)
|
||||
{
|
||||
mongo::BSONObjIterator iterator(doc);
|
||||
for (int i = 0; iterator.more(); ++i)
|
||||
{
|
||||
mongo::BSONElement element = iterator.next();
|
||||
if(i==index){
|
||||
if (i == index) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
@@ -722,7 +733,7 @@ namespace Robomongo
|
||||
int elementsCount(const mongo::BSONObj &doc)
|
||||
{
|
||||
mongo::BSONObjIterator iterator(doc);
|
||||
int i=0;
|
||||
int i = 0;
|
||||
for (; iterator.more(); ++i)
|
||||
{
|
||||
iterator.next();
|
||||
|
||||
@@ -100,8 +100,8 @@ namespace Robomongo
|
||||
|
||||
const char* BSONTypeToString(mongo::BSONType type, mongo::BinDataType binDataType, UUIDEncoding uuidEncoding);
|
||||
|
||||
void buildJsonString(const mongo::BSONObj &obj,std::string &con, UUIDEncoding uuid, SupportedTimes tz);
|
||||
void buildJsonString(const mongo::BSONElement &elem,std::string &con, UUIDEncoding uuid, SupportedTimes tz);
|
||||
void buildJsonString(const mongo::BSONObj &obj, std::string &con, UUIDEncoding uuid, SupportedTimes tz);
|
||||
void buildJsonString(const mongo::BSONElement &elem, std::string &con, UUIDEncoding uuid, SupportedTimes tz);
|
||||
|
||||
mongo::BSONElement indexOf(const mongo::BSONObj &doc, int index);
|
||||
int elementsCount(const mongo::BSONObj &doc);
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Robomongo
|
||||
|
||||
void cleanUpThread(QThread *const thread)
|
||||
{
|
||||
if (thread&&thread->isRunning()) {
|
||||
if (thread && thread->isRunning()) {
|
||||
//thread->stop();
|
||||
thread->wait();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,6 @@ namespace Robomongo
|
||||
static const QString StyleName;
|
||||
virtual void drawControl(ControlElement element, const QStyleOption * option, QPainter * painter, const QWidget * widget) const;
|
||||
virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const;
|
||||
virtual QRect subElementRect( SubElement element, const QStyleOption * option, const QWidget * widget=0 ) const;
|
||||
virtual QRect subElementRect( SubElement element, const QStyleOption * option, const QWidget * widget = 0 ) const;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -223,16 +223,28 @@ namespace Robomongo
|
||||
|
||||
const QIcon &GuiRegistry::noMarkIcon() const
|
||||
{
|
||||
static const QIcon noMarkIc = QIcon(":/robomongo/icons/no_mark_16x16.png");
|
||||
static const QIcon noMarkIc = QIcon(":/robomongo/icons/no_mark_24x24.png");
|
||||
return noMarkIc;
|
||||
}
|
||||
|
||||
const QIcon &GuiRegistry::yesMarkIcon() const
|
||||
{
|
||||
static const QIcon yesMarkIc = QIcon(":/robomongo/icons/yes_mark_16x16.png");
|
||||
static const QIcon yesMarkIc = QIcon(":/robomongo/icons/yes_mark_24x24.png");
|
||||
return yesMarkIc;
|
||||
}
|
||||
|
||||
const QIcon &GuiRegistry::skipMarkIcon() const
|
||||
{
|
||||
static const QIcon skipMarkIc = QIcon(":/robomongo/icons/skip_mark_24x24.png");
|
||||
return skipMarkIc;
|
||||
}
|
||||
|
||||
const QIcon &GuiRegistry::questionMarkIcon() const
|
||||
{
|
||||
static const QIcon questionMarkIc = QIcon(":/robomongo/icons/question_mark_24x24.png");
|
||||
return questionMarkIc;
|
||||
}
|
||||
|
||||
const QIcon &GuiRegistry::timeIcon() const
|
||||
{
|
||||
static const QIcon timeIc = QIcon(":/robomongo/icons/time_16x16.png");
|
||||
@@ -247,7 +259,7 @@ namespace Robomongo
|
||||
|
||||
const QBrush &GuiRegistry::typeBrush() const
|
||||
{
|
||||
static const QBrush typeBrush = QBrush(QColor(150,150, 150));
|
||||
static const QBrush typeBrush = QBrush(QColor(150, 150, 150));
|
||||
return typeBrush;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@ namespace Robomongo
|
||||
const QIcon &bsonBooleanIcon() const;
|
||||
const QIcon &noMarkIcon() const;
|
||||
const QIcon &yesMarkIcon() const;
|
||||
const QIcon &skipMarkIcon() const;
|
||||
const QIcon &questionMarkIcon() const;
|
||||
const QIcon &timeIcon() const;
|
||||
const QIcon &keyIcon() const;
|
||||
|
||||
|
||||
@@ -323,17 +323,17 @@ namespace Robomongo
|
||||
AutocompletionMode autocompletionMode = AppRegistry::instance().settingsManager()->autocompletionMode();
|
||||
|
||||
// Autocompletion
|
||||
QAction *autocompletionAllAction = new QAction("All",this);
|
||||
QAction *autocompletionAllAction = new QAction("All", this);
|
||||
autocompletionAllAction->setCheckable(true);
|
||||
autocompletionAllAction->setChecked(autocompletionMode == AutocompleteAll);
|
||||
VERIFY(connect(autocompletionAllAction, SIGNAL(triggered()), this, SLOT(setShellAutocompletionAll())));
|
||||
|
||||
QAction *autocompletionNoCollectionNamesAction = new QAction("All (Except Collection Names)",this);
|
||||
QAction *autocompletionNoCollectionNamesAction = new QAction("All (Except Collection Names)", this);
|
||||
autocompletionNoCollectionNamesAction->setCheckable(true);
|
||||
autocompletionNoCollectionNamesAction->setChecked(autocompletionMode == AutocompleteNoCollectionNames);
|
||||
VERIFY(connect(autocompletionNoCollectionNamesAction, SIGNAL(triggered()), this, SLOT(setShellAutocompletionNoCollectionNames())));
|
||||
|
||||
QAction *autocompletionNoneAction = new QAction("None",this);
|
||||
QAction *autocompletionNoneAction = new QAction("None", this);
|
||||
autocompletionNoneAction->setCheckable(true);
|
||||
autocompletionNoneAction->setChecked(autocompletionMode == AutocompleteNone);
|
||||
VERIFY(connect(autocompletionNoneAction, SIGNAL(triggered()), this, SLOT(setShellAutocompletionNone())));
|
||||
@@ -348,7 +348,7 @@ namespace Robomongo
|
||||
autocompletionGroup->addAction(autocompletionNoCollectionNamesAction);
|
||||
autocompletionGroup->addAction(autocompletionNoneAction);
|
||||
|
||||
QAction *loadMongoRcJs = new QAction("Load .mongorc.js",this);
|
||||
QAction *loadMongoRcJs = new QAction("Load .mongorc.js", this);
|
||||
loadMongoRcJs->setCheckable(true);
|
||||
loadMongoRcJs->setChecked(AppRegistry::instance().settingsManager()->loadMongoRcJs());
|
||||
VERIFY(connect(loadMongoRcJs, SIGNAL(triggered()), this, SLOT(setLoadMongoRcJs())));
|
||||
@@ -369,19 +369,19 @@ namespace Robomongo
|
||||
VERIFY(connect(showLineNumbers, SIGNAL(triggered()), this, SLOT(toggleLineNumbers())));
|
||||
optionsMenu->addAction(showLineNumbers);
|
||||
|
||||
QAction *disabelConnectionShortcuts = new QAction("Disable Connection Shortcuts",this);
|
||||
QAction *disabelConnectionShortcuts = new QAction("Disable Connection Shortcuts", this);
|
||||
disabelConnectionShortcuts->setCheckable(true);
|
||||
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);
|
||||
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);
|
||||
|
||||
QAction *preferencesAction = new QAction("Preferences",this);
|
||||
QAction *preferencesAction = new QAction("Preferences", this);
|
||||
VERIFY(connect(preferencesAction, SIGNAL(triggered()), this, SLOT(openPreferences())));
|
||||
preferencesAction->setVisible(false);
|
||||
optionsMenu->addAction(preferencesAction);
|
||||
@@ -516,7 +516,7 @@ namespace Robomongo
|
||||
const QString ¤tStyle = AppRegistry::instance().settingsManager()->currentStyle();
|
||||
for (QStringList::const_iterator it = supportedStyles.begin(); it != supportedStyles.end(); ++it) {
|
||||
const QString &style = *it;
|
||||
QAction *styleAction = new QAction(style,this);
|
||||
QAction *styleAction = new QAction(style, this);
|
||||
styleAction->setCheckable(true);
|
||||
styleAction->setChecked(style == currentStyle);
|
||||
styleGroup->addAction(styleAction);
|
||||
@@ -614,7 +614,7 @@ namespace Robomongo
|
||||
int number = 1;
|
||||
// Populate list with connections
|
||||
SettingsManager::ConnectionSettingsContainerType connections = AppRegistry::instance().settingsManager()->connections();
|
||||
for(SettingsManager::ConnectionSettingsContainerType::const_iterator it = connections.begin(); it!= connections.end(); ++it) {
|
||||
for (SettingsManager::ConnectionSettingsContainerType::const_iterator it = connections.begin(); it != connections.end(); ++it) {
|
||||
ConnectionSettings *connection = *it;
|
||||
QAction *action = new QAction(QtUtils::toQString(connection->getReadableName()), this);
|
||||
action->setData(QVariant::fromValue(connection));
|
||||
@@ -663,7 +663,7 @@ namespace Robomongo
|
||||
}
|
||||
|
||||
try {
|
||||
_app->openServer(selected, true);
|
||||
_app->openServer(selected, ConnectionPrimary);
|
||||
} catch(const std::exception &) {
|
||||
QString message = QString("Cannot connect to MongoDB (%1)").arg(QtUtils::toQString(selected->getFullAddress()));
|
||||
QMessageBox::information(this, "Error", message);
|
||||
@@ -788,7 +788,7 @@ namespace Robomongo
|
||||
|
||||
void MainWindow::refreshConnections()
|
||||
{
|
||||
QToolTip::showText(QPoint(0,0),
|
||||
QToolTip::showText(QPoint(0, 0),
|
||||
QString("Refresh not working yet... : <br/> <b>Ctrl+D</b> : push Button"));
|
||||
}
|
||||
|
||||
@@ -883,7 +883,7 @@ namespace Robomongo
|
||||
QVariant data = connectionAction->data();
|
||||
ConnectionSettings *ptr = data.value<ConnectionSettings *>();
|
||||
try {
|
||||
_app->openServer(ptr, true);
|
||||
_app->openServer(ptr, ConnectionPrimary);
|
||||
}
|
||||
catch(const std::exception &) {
|
||||
QString message = QString("Cannot connect to the MongoDB at %1.")
|
||||
@@ -894,6 +894,18 @@ namespace Robomongo
|
||||
|
||||
void MainWindow::handle(ConnectionFailedEvent *event)
|
||||
{
|
||||
// Handle only Primary connections
|
||||
if (event->connectionType != ConnectionPrimary)
|
||||
return;
|
||||
|
||||
|
||||
// Very temporary solution to prevent multiple connection error messages
|
||||
// from both SshTunnelWorker and MongoWorker
|
||||
static int lastServerHandle = -1;
|
||||
if (event->serverHandle <= lastServerHandle)
|
||||
return;
|
||||
|
||||
lastServerHandle = event->serverHandle;
|
||||
QMessageBox::information(this, "Error", QtUtils::toQString(event->message));
|
||||
}
|
||||
|
||||
|
||||
@@ -57,23 +57,20 @@ namespace Robomongo
|
||||
_mechanismComboBox->setCurrentText(QtUtils::toQString(primaryCredential->mechanism()));
|
||||
}
|
||||
|
||||
QGridLayout *_authLayout = new QGridLayout;
|
||||
_authLayout->addWidget(_useAuth, 0, 0, 1, 3);
|
||||
_authLayout->addWidget(_databaseNameLabel, 1, 0);
|
||||
_authLayout->addWidget(_databaseName, 1, 1, 1, 2);
|
||||
_authLayout->addWidget(_databaseNameDescriptionLabel, 2, 1, 1, 2);
|
||||
_authLayout->addWidget(_userNameLabel, 3, 0);
|
||||
_authLayout->addWidget(_userName, 3, 1, 1, 2);
|
||||
_authLayout->addWidget(_userPasswordLabel, 4, 0);
|
||||
_authLayout->addWidget(_userPassword, 4, 1);
|
||||
_authLayout->addWidget(_echoModeButton, 4, 2);
|
||||
_authLayout->addWidget(_mechanismLabel, 5, 0);
|
||||
_authLayout->addWidget(_mechanismComboBox, 5, 1, 1, 2);
|
||||
_authLayout->setAlignment(Qt::AlignTop);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(_authLayout);
|
||||
setLayout(mainLayout);
|
||||
QGridLayout *authLayout = new QGridLayout;
|
||||
authLayout->addWidget(_useAuth, 0, 0, 1, 3);
|
||||
authLayout->addWidget(_databaseNameLabel, 1, 0);
|
||||
authLayout->addWidget(_databaseName, 1, 1, 1, 2);
|
||||
authLayout->addWidget(_databaseNameDescriptionLabel, 2, 1, 1, 2);
|
||||
authLayout->addWidget(_userNameLabel, 3, 0);
|
||||
authLayout->addWidget(_userName, 3, 1, 1, 2);
|
||||
authLayout->addWidget(_userPasswordLabel, 4, 0);
|
||||
authLayout->addWidget(_userPassword, 4, 1);
|
||||
authLayout->addWidget(_echoModeButton, 4, 2);
|
||||
authLayout->addWidget(_mechanismLabel, 5, 0);
|
||||
authLayout->addWidget(_mechanismComboBox, 5, 1, 1, 2);
|
||||
authLayout->setAlignment(Qt::AlignTop);
|
||||
setLayout(authLayout);
|
||||
}
|
||||
|
||||
void ConnectionAuthTab::accept()
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Robomongo
|
||||
_serverAddress = new QLineEdit(QtUtils::toQString(_settings->serverHost()));
|
||||
_serverPort = new QLineEdit(QString::number(_settings->serverPort()));
|
||||
_serverPort->setFixedWidth(80);
|
||||
QRegExp rx("\\d+");//(0-65554)
|
||||
QRegExp rx("\\d+"); //(0-65554)
|
||||
_serverPort->setValidator(new QRegExpValidator(rx, this));
|
||||
|
||||
QGridLayout *connectionLayout = new QGridLayout;
|
||||
|
||||
@@ -5,169 +5,261 @@
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QMovie>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <mongo/client/dbclientinterface.h>
|
||||
#include "robomongo/core/settings/ConnectionSettings.h"
|
||||
#include "robomongo/core/settings/CredentialSettings.h"
|
||||
#include "robomongo/core/settings/SshSettings.h"
|
||||
#include "robomongo/gui/GuiRegistry.h"
|
||||
#include "robomongo/core/AppRegistry.h"
|
||||
#include "robomongo/core/domain/App.h"
|
||||
#include "robomongo/core/domain/MongoServer.h"
|
||||
#include "robomongo/core/EventBus.h"
|
||||
#include "robomongo/core/utils/QtUtils.h"
|
||||
#include "robomongo/core/mongodb/SshTunnelWorker.h"
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
const QSize ConnectionDiagnosticDialog::dialogSize = QSize(300,200);
|
||||
|
||||
ConnectionDiagnosticDialog::ConnectionDiagnosticDialog(ConnectionSettings *connection, QWidget *parent) :
|
||||
BaseClass(parent),
|
||||
_connection(connection),
|
||||
_connectionStatusReceived(false),
|
||||
_authStatusReceived(false)
|
||||
QDialog(parent),
|
||||
_connection(NULL),
|
||||
_server(NULL),
|
||||
_serverHandle(0),
|
||||
_continueExec(true)
|
||||
{
|
||||
_connection = connection->clone();
|
||||
|
||||
AppRegistry::instance().bus()->subscribe(this, ConnectionEstablishedEvent::Type);
|
||||
AppRegistry::instance().bus()->subscribe(this, ConnectionFailedEvent::Type);
|
||||
|
||||
setWindowTitle("Diagnostic");
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); // Remove help button (?)
|
||||
//setFixedSize(dialogSize);
|
||||
|
||||
_yesIcon = GuiRegistry::instance().yesMarkIcon();
|
||||
_noIcon = GuiRegistry::instance().noMarkIcon();
|
||||
_yesPixmap = _yesIcon.pixmap(24, 24);
|
||||
_noPixmap = _noIcon.pixmap(24, 24);
|
||||
_questionIcon = GuiRegistry::instance().questionMarkIcon();
|
||||
_yesPixmap = _yesIcon.pixmap(20, 20);
|
||||
_noPixmap = _noIcon.pixmap(20, 20);
|
||||
_questionPixmap = _questionIcon.pixmap(20, 20);
|
||||
|
||||
QPushButton *closeButton = new QPushButton("&Close");
|
||||
VERIFY(connect(closeButton, SIGNAL(clicked()), this, SLOT(accept())));
|
||||
_connectionIconLabel = new QLabel;
|
||||
_authIconLabel = new QLabel;
|
||||
_connectionLabel = new QLabel;
|
||||
_authIconLabel = new QLabel;
|
||||
_authLabel = new QLabel;
|
||||
_sshIconLabel = new QLabel;
|
||||
_sshLabel = new QLabel;
|
||||
_listIconLabel = new QLabel;
|
||||
_listLabel = new QLabel;
|
||||
|
||||
_loadingMovie = new QMovie(":robomongo/icons/loading.gif", QByteArray(), this);
|
||||
_viewErrorLink = new QLabel("<a href='error' style='color: #777777;'>Show error details</a>");
|
||||
VERIFY(connect(_viewErrorLink, SIGNAL(linkActivated(QString)), this, SLOT(errorLinkActivated(QString))));
|
||||
|
||||
_loadingMovie = new QMovie(":robomongo/icons/loading_ticks_40x40.gif", QByteArray(), this);
|
||||
_loadingMovie->setScaledSize(QSize(20, 20));
|
||||
_loadingMovie->start();
|
||||
|
||||
_connectionIconLabel->setMovie(_loadingMovie);
|
||||
_sshIconLabel->setMovie(_loadingMovie);
|
||||
_authIconLabel->setMovie(_loadingMovie);
|
||||
|
||||
_connectionLabel->setText(QString("Connecting to <b>%1</b>...").arg(QtUtils::toQString(_connection->getFullAddress())));
|
||||
|
||||
if (_connection->hasEnabledPrimaryCredential()) {
|
||||
_authLabel->setText(QString("Authorizing on <b>%1</b> database as <b>%2</b>...")
|
||||
.arg(QtUtils::toQString(_connection->primaryCredential()->databaseName()))
|
||||
.arg(QtUtils::toQString(_connection->primaryCredential()->userName())));
|
||||
} else {
|
||||
_authLabel->setText("Authorization skipped by you");
|
||||
}
|
||||
_listIconLabel->setMovie(_loadingMovie);
|
||||
|
||||
QGridLayout *layout = new QGridLayout();
|
||||
layout->setContentsMargins(20, 20, 20, 10);
|
||||
layout->addWidget(_connectionIconLabel, 0, 0);
|
||||
layout->addWidget(_connectionLabel, 0, 1, Qt::AlignLeft);
|
||||
layout->addWidget(_authIconLabel, 1, 0);
|
||||
layout->addWidget(_authLabel, 1, 1, Qt::AlignLeft);
|
||||
layout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
layout->addWidget(_sshIconLabel, 0, 0);
|
||||
layout->addWidget(_sshLabel, 0, 1, Qt::AlignLeft);
|
||||
layout->addWidget(_connectionIconLabel, 1, 0);
|
||||
layout->addWidget(_connectionLabel, 1, 1, Qt::AlignLeft);
|
||||
layout->addWidget(_authIconLabel, 2, 0);
|
||||
layout->addWidget(_authLabel, 2, 1, Qt::AlignLeft);
|
||||
layout->addWidget(_listIconLabel, 3, 0);
|
||||
layout->addWidget(_listLabel, 3, 1, Qt::AlignLeft);
|
||||
layout->setColumnStretch(0, 0) ; // Give column 0 no stretch ability
|
||||
layout->setColumnStretch(1, 1) ; // Give column 1 stretch ability of ratio 1
|
||||
|
||||
QHBoxLayout *hbox = new QHBoxLayout;
|
||||
hbox->addSpacing(21);
|
||||
hbox->addWidget(_viewErrorLink, 1, Qt::AlignLeft);
|
||||
hbox->addWidget(closeButton, 0, Qt::AlignRight);
|
||||
|
||||
QVBoxLayout *box = new QVBoxLayout;
|
||||
box->addLayout(layout);
|
||||
box->addSpacing(10);
|
||||
box->addWidget(closeButton, 0, Qt::AlignRight);
|
||||
box->addLayout(hbox);
|
||||
setLayout(box);
|
||||
|
||||
ConnectionDiagnosticThread *thread = new ConnectionDiagnosticThread(_connection);
|
||||
VERIFY(connect(thread, SIGNAL(connectionStatus(QString, bool)), this, SLOT(connectionStatus(QString, bool))));
|
||||
VERIFY(connect(thread, SIGNAL(authStatus(QString, bool)), this, SLOT(authStatus(QString, bool))));
|
||||
VERIFY(connect(thread, SIGNAL(completed()), this, SLOT(completed())));
|
||||
VERIFY(connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())));
|
||||
thread->start();
|
||||
}
|
||||
sshStatus(InitialState);
|
||||
connectionStatus(InitialState);
|
||||
authStatus(InitialState);
|
||||
listStatus(InitialState);
|
||||
|
||||
void ConnectionDiagnosticDialog::connectionStatus(QString error, bool connected)
|
||||
{
|
||||
_connectionStatusReceived = true;
|
||||
_viewErrorLink->hide();
|
||||
|
||||
if (connected) {
|
||||
_connectionIconLabel->setPixmap(_yesPixmap);
|
||||
_connectionLabel->setText(QString("Connected to <b>%1</b>").arg(QtUtils::toQString(_connection->getFullAddress())));
|
||||
} else {
|
||||
_connectionIconLabel->setPixmap(_noPixmap);
|
||||
_connectionLabel->setText(QString("Unable to connect to <b>%1</b>").arg(QtUtils::toQString(_connection->getFullAddress())));
|
||||
}
|
||||
|
||||
layout()->activate();
|
||||
setFixedSize(minimumSizeHint());
|
||||
}
|
||||
|
||||
void ConnectionDiagnosticDialog::authStatus(QString error, bool authed)
|
||||
{
|
||||
_authStatusReceived = true;
|
||||
|
||||
if (authed) {
|
||||
_authIconLabel->setPixmap(_yesPixmap);
|
||||
_authLabel->setText(QString("Authorized as <b>%1</b>").arg(QtUtils::toQString(_connection->primaryCredential()->userName())));
|
||||
} else {
|
||||
|
||||
_authIconLabel->setPixmap(_noPixmap);
|
||||
|
||||
if (_connection->hasEnabledPrimaryCredential())
|
||||
_authLabel->setText(QString("Authorization failed"));
|
||||
else
|
||||
_authLabel->setText(QString("Authorization skipped by you"));
|
||||
}
|
||||
|
||||
layout()->activate();
|
||||
setFixedSize(minimumSizeHint());
|
||||
}
|
||||
|
||||
void ConnectionDiagnosticDialog::completed()
|
||||
{
|
||||
if (!_connectionStatusReceived)
|
||||
connectionStatus("", false);
|
||||
|
||||
if (!_authStatusReceived)
|
||||
authStatus("", false);
|
||||
|
||||
// seems that it is wrong to call any method on thread,
|
||||
// because thread already can be disposed.
|
||||
// QThread *thread = static_cast<QThread *>(sender());
|
||||
// thread->quit();
|
||||
}
|
||||
|
||||
|
||||
ConnectionDiagnosticThread::ConnectionDiagnosticThread(ConnectionSettings *connection) :
|
||||
_connection(connection) { }
|
||||
|
||||
void ConnectionDiagnosticThread::run()
|
||||
{
|
||||
boost::scoped_ptr<mongo::DBClientConnection> connection;
|
||||
|
||||
try {
|
||||
connection.reset(new mongo::DBClientConnection);
|
||||
connection->connect(_connection->info());
|
||||
emit connectionStatus("", true);
|
||||
}
|
||||
catch(const mongo::UserException &ex) {
|
||||
const char *what = ex.what();
|
||||
emit connectionStatus(QString(what), false);
|
||||
emit completed();
|
||||
if (!AppRegistry::instance().app()->openServer(_connection, ConnectionTest)) {
|
||||
_continueExec = false;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (_connection->hasEnabledPrimaryCredential())
|
||||
{
|
||||
CredentialSettings *credentials = _connection->primaryCredential();
|
||||
_serverHandle = AppRegistry::instance().app()->getLastServerHandle();
|
||||
}
|
||||
|
||||
// Building BSON object:
|
||||
mongo::BSONObj authParams(mongo::BSONObjBuilder()
|
||||
.append("user", credentials->userName())
|
||||
.append("db", credentials->databaseName())
|
||||
.append("pwd", credentials->userPassword())
|
||||
.append("mechanism", credentials->mechanism())
|
||||
.obj());
|
||||
ConnectionDiagnosticDialog::~ConnectionDiagnosticDialog() {
|
||||
if (_server)
|
||||
AppRegistry::instance().app()->closeServer(_server);
|
||||
}
|
||||
|
||||
connection->auth(authParams);
|
||||
emit authStatus("", true);
|
||||
}
|
||||
} catch (const mongo::UserException &ex) {
|
||||
emit authStatus("", false);
|
||||
void ConnectionDiagnosticDialog::errorLinkActivated(const QString &link) {
|
||||
if (_lastErrorMessage.empty())
|
||||
return;
|
||||
|
||||
QMessageBox::information(this, "Error details", QtUtils::toQString(_lastErrorMessage));
|
||||
}
|
||||
|
||||
void ConnectionDiagnosticDialog::sshStatus(State state)
|
||||
{
|
||||
if (!_connection->sshSettings()->enabled()) {
|
||||
_sshIconLabel->setVisible(false);
|
||||
_sshLabel->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
emit completed();
|
||||
if (state == InitialState) {
|
||||
_sshIconLabel->setMovie(_loadingMovie);
|
||||
_sshLabel->setText(QString("Connecting to SSH server at <b>%1:%2</b>...")
|
||||
.arg(QtUtils::toQString(_connection->sshSettings()->host()))
|
||||
.arg(_connection->sshSettings()->port()));
|
||||
} else if (state == CompletedState) {
|
||||
_sshIconLabel->setPixmap(_yesPixmap);
|
||||
_sshLabel->setText(QString("Connected to SSH server at <b>%1:%2</b>")
|
||||
.arg(QtUtils::toQString(_connection->sshSettings()->host()))
|
||||
.arg(_connection->sshSettings()->port()));
|
||||
} else if (state == FailedState) {
|
||||
_sshIconLabel->setPixmap(_noPixmap);
|
||||
_sshLabel->setText(QString("Unable to connect to SSH server at <b>%1:%2</b>")
|
||||
.arg(QtUtils::toQString(_connection->sshSettings()->host()))
|
||||
.arg(_connection->sshSettings()->port()));
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionDiagnosticDialog::connectionStatus(State state)
|
||||
{
|
||||
if (state == InitialState) {
|
||||
_connectionIconLabel->setMovie(_loadingMovie);
|
||||
QString tunnelNote = _connection->sshSettings()->enabled() ? " via SSH tunnel" : "";
|
||||
_connectionLabel->setText(QString("Connecting to <b>%1</b>%2...").arg(QtUtils::toQString(_connection->getFullAddress()), tunnelNote));
|
||||
} else if (state == CompletedState) {
|
||||
_connectionIconLabel->setPixmap(_yesPixmap);
|
||||
QString tunnelNote = _connection->sshSettings()->enabled() ? " via SSH tunnel" : "";
|
||||
_connectionLabel->setText(QString("Connected to <b>%1</b>%2").arg(QtUtils::toQString(_connection->getFullAddress()), tunnelNote));
|
||||
} else if (state == FailedState) {
|
||||
_connectionIconLabel->setPixmap(_noPixmap);
|
||||
QString tunnelNote = _connection->sshSettings()->enabled() ? " via tunnel" : "";
|
||||
_connectionLabel->setText(QString("Failed to connect to <b>%1</b>%2").arg(QtUtils::toQString(_connection->getFullAddress()), tunnelNote));
|
||||
} else if (state == NotPerformedState) {
|
||||
_connectionIconLabel->setPixmap(_questionPixmap);
|
||||
QString tunnelNote = _connection->sshSettings()->enabled() ? " via SSH tunnel" : "";
|
||||
_connectionLabel->setText(QString("No chance to try connection to <b>%1</b>%2").arg(QtUtils::toQString(_connection->getFullAddress()), tunnelNote));
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionDiagnosticDialog::authStatus(State state)
|
||||
{
|
||||
if (!_connection->hasEnabledPrimaryCredential()) {
|
||||
_authIconLabel->setVisible(false);
|
||||
_authLabel->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == InitialState) {
|
||||
_authIconLabel->setMovie(_loadingMovie);
|
||||
_authLabel->setText(QString("Authorizing on <b>%1</b> database as <b>%2</b>...")
|
||||
.arg(QtUtils::toQString(_connection->primaryCredential()->databaseName()))
|
||||
.arg(QtUtils::toQString(_connection->primaryCredential()->userName())));
|
||||
} else if (state == CompletedState) {
|
||||
_authIconLabel->setPixmap(_yesPixmap);
|
||||
_authLabel->setText(QString("Authorized on <b>%1</b> database as <b>%2</b>")
|
||||
.arg(QtUtils::toQString(_connection->primaryCredential()->databaseName()))
|
||||
.arg(QtUtils::toQString(_connection->primaryCredential()->userName())));
|
||||
} else if (state == FailedState) {
|
||||
_authIconLabel->setPixmap(_noPixmap);
|
||||
_authLabel->setText(QString("Authorization failed on <b>%1</b> database as <b>%2</b>")
|
||||
.arg(QtUtils::toQString(_connection->primaryCredential()->databaseName()))
|
||||
.arg(QtUtils::toQString(_connection->primaryCredential()->userName())));
|
||||
} else if (state == NotPerformedState) {
|
||||
_authIconLabel->setPixmap(_questionPixmap);
|
||||
_authLabel->setText(QString("No chance to authorize"));
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionDiagnosticDialog::listStatus(State state)
|
||||
{
|
||||
if (_connection->hasEnabledPrimaryCredential()) {
|
||||
_listIconLabel->setVisible(false);
|
||||
_listLabel->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == InitialState) {
|
||||
_listIconLabel->setMovie(_loadingMovie);
|
||||
_listLabel->setText(QString("Loading list of databases..."));
|
||||
} else if (state == CompletedState) {
|
||||
_listIconLabel->setPixmap(_yesPixmap);
|
||||
_listLabel->setText(QString("Access to databases is available"));
|
||||
} else if (state == FailedState) {
|
||||
_listIconLabel->setPixmap(_noPixmap);
|
||||
_listLabel->setText(QString("Failed to load list of databases"));
|
||||
} else if (state == NotPerformedState) {
|
||||
_listIconLabel->setPixmap(_questionPixmap);
|
||||
_listLabel->setText(QString("No chance to load list of databases"));
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionDiagnosticDialog::handle(ConnectionEstablishedEvent *event) {
|
||||
if (event->connectionType != ConnectionTest)
|
||||
return;
|
||||
|
||||
sshStatus(CompletedState);
|
||||
connectionStatus(CompletedState);
|
||||
authStatus(CompletedState);
|
||||
listStatus(CompletedState);
|
||||
|
||||
// Remember in order to delete on dialog close
|
||||
_server = static_cast<MongoServer*>(event->sender());
|
||||
}
|
||||
|
||||
void ConnectionDiagnosticDialog::handle(ConnectionFailedEvent *event) {
|
||||
if (event->connectionType != ConnectionTest || event->serverHandle != _serverHandle)
|
||||
return;
|
||||
|
||||
sshStatus(CompletedState);
|
||||
connectionStatus(CompletedState);
|
||||
authStatus(CompletedState);
|
||||
listStatus(CompletedState);
|
||||
|
||||
switch (event->reason) {
|
||||
case ConnectionFailedEvent::SshConnection:
|
||||
sshStatus(FailedState);
|
||||
connectionStatus(NotPerformedState);
|
||||
authStatus(NotPerformedState);
|
||||
listStatus(NotPerformedState);
|
||||
break;
|
||||
case ConnectionFailedEvent::SshChannel:
|
||||
case ConnectionFailedEvent::MongoConnection:
|
||||
connectionStatus(FailedState);
|
||||
authStatus(NotPerformedState);
|
||||
listStatus(NotPerformedState);
|
||||
break;
|
||||
case ConnectionFailedEvent::MongoAuth:
|
||||
authStatus(FailedState);
|
||||
listStatus(FailedState);
|
||||
break;
|
||||
}
|
||||
|
||||
// Show link for additional error details
|
||||
if (!event->message.empty()) {
|
||||
_lastErrorMessage = event->message;
|
||||
_viewErrorLink->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,63 +2,69 @@
|
||||
|
||||
#include <QDialog>
|
||||
#include <QIcon>
|
||||
#include <QThread>
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QLabel;
|
||||
class QMovie;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
class ConnectionEstablishedEvent;
|
||||
class ConnectionFailedEvent;
|
||||
class ConnectionSettings;
|
||||
class MongoServer;
|
||||
|
||||
class ConnectionDiagnosticDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef QDialog BaseClass;
|
||||
static const QSize dialogSize;
|
||||
ConnectionDiagnosticDialog(ConnectionSettings *connection, QWidget *parent = 0);
|
||||
~ConnectionDiagnosticDialog();
|
||||
|
||||
bool continueExec() const { return _continueExec; }
|
||||
|
||||
protected Q_SLOTS:
|
||||
void connectionStatus(QString error, bool connected);
|
||||
void authStatus(QString error, bool authed);
|
||||
void completed();
|
||||
void handle(ConnectionEstablishedEvent *event);
|
||||
void handle(ConnectionFailedEvent *event);
|
||||
void errorLinkActivated(const QString &link);
|
||||
|
||||
private:
|
||||
|
||||
enum State {
|
||||
InitialState,
|
||||
CompletedState,
|
||||
FailedState,
|
||||
NotPerformedState
|
||||
};
|
||||
|
||||
void sshStatus(State state);
|
||||
void connectionStatus(State state);
|
||||
void authStatus(State state);
|
||||
void listStatus(State state);
|
||||
|
||||
ConnectionSettings *_connection;
|
||||
QIcon _yesIcon;
|
||||
QIcon _noIcon;
|
||||
QIcon _waitIcon;
|
||||
QIcon _questionIcon;
|
||||
QMovie *_loadingMovie;
|
||||
|
||||
QPixmap _yesPixmap;
|
||||
QPixmap _noPixmap;
|
||||
QPixmap _questionPixmap;
|
||||
|
||||
QLabel *_sshIconLabel;
|
||||
QLabel *_sshLabel;
|
||||
QLabel *_connectionIconLabel;
|
||||
QLabel *_connectionLabel;
|
||||
QLabel *_authIconLabel;
|
||||
QLabel *_authLabel;
|
||||
QLabel *_listIconLabel; // List database names
|
||||
QLabel *_listLabel;
|
||||
|
||||
bool _connectionStatusReceived;
|
||||
bool _authStatusReceived;
|
||||
};
|
||||
QLabel *_viewErrorLink;
|
||||
std::string _lastErrorMessage;
|
||||
|
||||
class ConnectionDiagnosticThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ConnectionDiagnosticThread(ConnectionSettings *connection);
|
||||
|
||||
Q_SIGNALS:
|
||||
void connectionStatus(QString error, bool connected);
|
||||
void authStatus(QString error, bool authed);
|
||||
void completed();
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
ConnectionSettings *_connection;
|
||||
MongoServer *_server;
|
||||
int _serverHandle;
|
||||
bool _continueExec;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ namespace Robomongo
|
||||
|
||||
tabWidget->addTab(_basicTab, "Connection");
|
||||
tabWidget->addTab(_authTab, "Authentication");
|
||||
tabWidget->addTab(_advancedTab, "Advanced");
|
||||
tabWidget->addTab(_sshTab, "SSH");
|
||||
tabWidget->addTab(_advancedTab, "Advanced");
|
||||
|
||||
// v0.9
|
||||
//tabWidget->addTab(_sslTab, "SSL");
|
||||
@@ -76,7 +76,7 @@ namespace Robomongo
|
||||
*/
|
||||
void ConnectionDialog::accept()
|
||||
{
|
||||
if (validateAndApply()){
|
||||
if (validateAndApply()) {
|
||||
QDialog::accept();
|
||||
}
|
||||
}
|
||||
@@ -93,7 +93,9 @@ namespace Robomongo
|
||||
_basicTab->accept();
|
||||
_authTab->accept();
|
||||
_advancedTab->accept();
|
||||
_sshTab->accept();
|
||||
|
||||
if (!_sshTab->accept())
|
||||
return false;
|
||||
|
||||
// v0.9
|
||||
// _sslTab->accept();
|
||||
@@ -105,9 +107,13 @@ namespace Robomongo
|
||||
*/
|
||||
void ConnectionDialog::testConnection()
|
||||
{
|
||||
if(validateAndApply()){
|
||||
ConnectionDiagnosticDialog diag(_connection,this);
|
||||
diag.exec();
|
||||
}
|
||||
if (!validateAndApply())
|
||||
return;
|
||||
|
||||
ConnectionDiagnosticDialog diag(_connection, this);
|
||||
if (!diag.continueExec())
|
||||
return;
|
||||
|
||||
diag.exec();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Robomongo
|
||||
_sslSupport->setChecked(_settings->sslInfo()._sslSupport);
|
||||
|
||||
_selectPemFileButton = new QPushButton("...");
|
||||
_selectPemFileButton->setFixedSize(20,20);
|
||||
_selectPemFileButton->setFixedSize(20, 20);
|
||||
VERIFY(connect(_selectPemFileButton, SIGNAL(clicked()), this, SLOT(setSslPEMKeyFile())));
|
||||
|
||||
_sslPemLabel = new QLabel("SSL Certificate:");
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace Robomongo
|
||||
activateWindow();
|
||||
|
||||
int size = _connectionItems.size();
|
||||
for (int i=0; i<size; ++i)
|
||||
for (int i = 0; i<size; ++i)
|
||||
{
|
||||
ConnectionListWidgetItem *item = _connectionItems[i];
|
||||
if (_connectionItems[i]->connection() == connection) {
|
||||
@@ -281,7 +281,7 @@ namespace Robomongo
|
||||
|
||||
// Clone connection
|
||||
ConnectionSettings *connection = currentItem->connection()->clone();
|
||||
std::string newConnectionName="Copy of "+connection->connectionName();
|
||||
std::string newConnectionName = "Copy of "+connection->connectionName();
|
||||
|
||||
connection->setConnectionName(newConnectionName);
|
||||
|
||||
@@ -307,7 +307,7 @@ namespace Robomongo
|
||||
|
||||
// Make childrens toplevel again. This is a bad, but quickiest item reordering
|
||||
// implementation.
|
||||
for(int i = 0; i < count; i++)
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
ConnectionListWidgetItem * item = (ConnectionListWidgetItem *) _listWidget->topLevelItem(i);
|
||||
if (item->childCount() > 0) {
|
||||
@@ -321,7 +321,7 @@ namespace Robomongo
|
||||
|
||||
count = _listWidget->topLevelItemCount();
|
||||
SettingsManager::ConnectionSettingsContainerType items;
|
||||
for(int i = 0; i < count; i++)
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
ConnectionListWidgetItem * item = (ConnectionListWidgetItem *) _listWidget->topLevelItem(i);
|
||||
items.push_back(item->connection());
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
const QSize CopyCollection::minimumSize = QSize(300,150);
|
||||
const QSize CopyCollection::minimumSize = QSize(300, 150);
|
||||
|
||||
CopyCollection::CopyCollection(const QString &serverName, const QString &database,
|
||||
const QString &collection, QWidget *parent) :
|
||||
@@ -28,9 +28,9 @@ namespace Robomongo
|
||||
{
|
||||
App::MongoServersContainerType servers = AppRegistry::instance().app()->getServers();
|
||||
QSet<QString> uniqueConnectionsNames;
|
||||
for(App::MongoServersContainerType::const_iterator it = servers.begin(); it != servers.end(); ++it){
|
||||
for (App::MongoServersContainerType::const_iterator it = servers.begin(); it != servers.end(); ++it) {
|
||||
MongoServer *server = *it;
|
||||
if (server->isConnected() ){
|
||||
if (server->isConnected()) {
|
||||
_servers.push_back(server);
|
||||
uniqueConnectionsNames.insert(QtUtils::toQString(server->connectionRecord()->connectionName()));
|
||||
}
|
||||
@@ -109,7 +109,7 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
_databaseComboBox->addItems(server->getDatabasesNames());
|
||||
if (_currentServerName==QtUtils::toQString(server->connectionRecord()->getFullAddress())) {
|
||||
if (_currentServerName == QtUtils::toQString(server->connectionRecord()->getFullAddress())) {
|
||||
_databaseComboBox->removeItem(_databaseComboBox->findText(_currentDatabase));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
const QSize CreateDatabaseDialog::dialogSize = QSize(300,150);
|
||||
const QSize CreateDatabaseDialog::dialogSize = QSize(300, 150);
|
||||
|
||||
CreateDatabaseDialog::CreateDatabaseDialog(const QString &serverName, const QString &database,
|
||||
const QString &collection, QWidget *parent) :
|
||||
@@ -31,7 +31,7 @@ namespace Robomongo
|
||||
hline->setFrameShadow(QFrame::Sunken);
|
||||
|
||||
_inputEdit = new QLineEdit();
|
||||
_inputLabel= new QLabel("Database Name:");
|
||||
_inputLabel = new QLabel("Database Name:");
|
||||
_inputEdit->setMaxLength(maxLenghtName);
|
||||
|
||||
_buttonBox = new QDialogButtonBox(this);
|
||||
|
||||
@@ -17,8 +17,19 @@
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
const char * rolesText[CreateUserDialog::RolesCount] = {"read","readWrite","dbAdmin","userAdmin","clusterAdmin","readAnyDatabase","readWriteAnyDatabase","userAdminAnyDatabase","dbAdminAnyDatabase"};
|
||||
const QSize CreateUserDialog::minimumSize = QSize(400,200);
|
||||
const char * rolesText[CreateUserDialog::RolesCount] = {
|
||||
"read",
|
||||
"readWrite",
|
||||
"dbAdmin",
|
||||
"userAdmin",
|
||||
"clusterAdmin",
|
||||
"readAnyDatabase",
|
||||
"readWriteAnyDatabase",
|
||||
"userAdminAnyDatabase",
|
||||
"dbAdminAnyDatabase"
|
||||
};
|
||||
|
||||
const QSize CreateUserDialog::minimumSize = QSize(400, 200);
|
||||
|
||||
bool containsWord(const std::string& sentence, const std::string& word)
|
||||
{
|
||||
@@ -31,7 +42,7 @@ namespace Robomongo
|
||||
if (pos) {
|
||||
isFirstAlpha = isalpha(sentence[pos - 1]);
|
||||
}
|
||||
if (!isFirstAlpha&&!isLastAlpha)
|
||||
if (!isFirstAlpha && !isLastAlpha)
|
||||
return true;
|
||||
}
|
||||
pos++;
|
||||
@@ -39,13 +50,11 @@ namespace Robomongo
|
||||
return false;
|
||||
}
|
||||
|
||||
CreateUserDialog::CreateUserDialog(const QStringList &databases,const QString &serverName,
|
||||
CreateUserDialog::CreateUserDialog(const QStringList &databases, const QString &serverName,
|
||||
const QString &database, const MongoUser &user,
|
||||
QWidget *parent) : QDialog(parent),
|
||||
_user(user)
|
||||
{
|
||||
VERIFY(!user.version() < MongoUser::minimumSupportedVersion);
|
||||
|
||||
setWindowTitle("Add User");
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); // Remove help button (?)
|
||||
setMinimumSize(minimumSize);
|
||||
@@ -57,10 +66,10 @@ namespace Robomongo
|
||||
hline->setFrameShape(QFrame::HLine);
|
||||
hline->setFrameShadow(QFrame::Sunken);
|
||||
|
||||
_userNameLabel= new QLabel("Name:");
|
||||
_userNameLabel = new QLabel("Name:");
|
||||
_userNameEdit = new QLineEdit();
|
||||
_userNameEdit->setText(QtUtils::toQString(user.name()));
|
||||
_userPassLabel= new QLabel("Password:");
|
||||
_userPassLabel = new QLabel("Password:");
|
||||
_userPassEdit = new QLineEdit();
|
||||
_userPassEdit->setEchoMode(QLineEdit::Password);
|
||||
_userSourceLabel = new QLabel("UserSource:");
|
||||
@@ -70,14 +79,14 @@ namespace Robomongo
|
||||
|
||||
QGridLayout *gridRoles = new QGridLayout();
|
||||
MongoUser::RoleType userRoles = user.role();
|
||||
for (unsigned i=0; i<RolesCount; ++i)
|
||||
for (unsigned i = 0; i<RolesCount; ++i)
|
||||
{
|
||||
int row = i%3;
|
||||
int col = i/3;
|
||||
_rolesArray[i] = new QCheckBox(rolesText[i],this);
|
||||
MongoUser::RoleType::const_iterator it = std::find(userRoles.begin(),userRoles.end(),rolesText[i]);
|
||||
_rolesArray[i]->setChecked(it!=userRoles.end());
|
||||
gridRoles->addWidget(_rolesArray[i],row,col);
|
||||
_rolesArray[i] = new QCheckBox(rolesText[i], this);
|
||||
MongoUser::RoleType::const_iterator it = std::find(userRoles.begin(), userRoles.end(), rolesText[i]);
|
||||
_rolesArray[i]->setChecked(it!= userRoles.end());
|
||||
gridRoles->addWidget(_rolesArray[i], row, col);
|
||||
}
|
||||
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(this);
|
||||
@@ -120,7 +129,6 @@ namespace Robomongo
|
||||
QWidget *parent) : QDialog(parent),
|
||||
_user(user)
|
||||
{
|
||||
VERIFY(user.version() < MongoUser::minimumSupportedVersion);
|
||||
setWindowTitle("Add User");
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); // Remove help button (?)
|
||||
setMinimumSize(minimumSize);
|
||||
@@ -132,7 +140,7 @@ namespace Robomongo
|
||||
hline->setFrameShape(QFrame::HLine);
|
||||
hline->setFrameShadow(QFrame::Sunken);
|
||||
|
||||
_userNameLabel= new QLabel("Name:");
|
||||
_userNameLabel = new QLabel("Name:");
|
||||
_userNameEdit = new QLineEdit();
|
||||
_userNameEdit->setText(QtUtils::toQString(user.name()));
|
||||
_userPassLabel= new QLabel("Password:");
|
||||
|
||||
@@ -36,10 +36,6 @@ namespace Robomongo
|
||||
|
||||
resize(size);
|
||||
|
||||
int x = (screenGeometry.width() - width()) / 2;
|
||||
int y = (screenGeometry.height() - height()) / 2;
|
||||
move(x, y);
|
||||
|
||||
setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
|
||||
|
||||
Indicator *collectionIndicator = new Indicator(GuiRegistry::instance().collectionIcon(), QtUtils::toQString(_info._ns.collectionName()));
|
||||
@@ -144,18 +140,18 @@ namespace Robomongo
|
||||
int jsonLen = textString.length();
|
||||
int offset = 0;
|
||||
_obj.clear();
|
||||
while(offset!=jsonLen)
|
||||
while (offset != jsonLen)
|
||||
{
|
||||
mongo::BSONObj doc = mongo::Robomongo::fromjson(json+offset,&len);
|
||||
mongo::BSONObj doc = mongo::Robomongo::fromjson(json+offset, &len);
|
||||
_obj.push_back(doc);
|
||||
offset+=len;
|
||||
offset += len;
|
||||
}
|
||||
} catch (const mongo::Robomongo::ParseMsgAssertionException &ex) {
|
||||
// v0.9
|
||||
QString message = QtUtils::toQString(ex.reason());
|
||||
int offset = ex.offset();
|
||||
|
||||
int line=0, pos=0;
|
||||
int line = 0, pos = 0;
|
||||
_queryText->sciScintilla()->lineIndexFromPosition(offset, &line, &pos);
|
||||
_queryText->sciScintilla()->setCursorPosition(line, pos);
|
||||
|
||||
@@ -198,7 +194,7 @@ namespace Robomongo
|
||||
QsciLexerJavaScript *javaScriptLexer = new JSLexer(this);
|
||||
QFont font = GuiRegistry::instance().font();
|
||||
javaScriptLexer->setFont(font);
|
||||
_queryText->sciScintilla()->setBraceMatching(QsciScintilla::StrictBraceMatch);
|
||||
_queryText->sciScintilla()->setAppropriateBraceMatching();
|
||||
_queryText->sciScintilla()->setFont(font);
|
||||
_queryText->sciScintilla()->setPaper(QColor(255, 0, 0, 127));
|
||||
_queryText->sciScintilla()->setLexer(javaScriptLexer);
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace Robomongo
|
||||
const QFont &textFont = GuiRegistry::instance().font();
|
||||
QsciLexerJavaScript *javaScriptLexer = new JSLexer(this);
|
||||
javaScriptLexer->setFont(textFont);
|
||||
_queryText->sciScintilla()->setBraceMatching(QsciScintilla::StrictBraceMatch);
|
||||
_queryText->sciScintilla()->setAppropriateBraceMatching();
|
||||
_queryText->sciScintilla()->setFont(textFont);
|
||||
_queryText->sciScintilla()->setPaper(QColor(255, 0, 0, 127));
|
||||
_queryText->sciScintilla()->setLexer(javaScriptLexer);
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Robomongo
|
||||
|
||||
setWindowTitle("Preferences " PROJECT_NAME_TITLE);
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setFixedSize(height,width);
|
||||
setFixedSize(height, width);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Robomongo
|
||||
defLayout->addWidget(defDisplayModeLabel);
|
||||
_defDisplayModeComboBox = new QComboBox();
|
||||
QStringList modes;
|
||||
for (int i = Text;i<=Custom;++i)
|
||||
for (int i = Text; i <= Custom; ++i)
|
||||
{
|
||||
modes.append(convertViewModeToString(static_cast<ViewMode>(i)));
|
||||
}
|
||||
@@ -46,7 +46,7 @@ namespace Robomongo
|
||||
timeZoneLayout->addWidget(timeZoneLabel);
|
||||
_timeZoneComboBox = new QComboBox();
|
||||
QStringList times;
|
||||
for (int i = Utc;i<=LocalTime;++i)
|
||||
for (int i = Utc; i <= LocalTime; ++i)
|
||||
{
|
||||
times.append(convertTimesToString(static_cast<SupportedTimes>(i)));
|
||||
}
|
||||
@@ -59,7 +59,7 @@ namespace Robomongo
|
||||
uuidEncodingLayout->addWidget(uuidEncodingLabel);
|
||||
_uuidEncodingComboBox = new QComboBox();
|
||||
QStringList uuids;
|
||||
for (int i = DefaultEncoding;i<=PythonLegacy;++i)
|
||||
for (int i = DefaultEncoding; i <= PythonLegacy; ++i)
|
||||
{
|
||||
uuids.append(convertUUIDEncodingToString(static_cast<UUIDEncoding>(i)));
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
#include <QComboBox>
|
||||
#include <QMessageBox>
|
||||
#include <QFileInfo>
|
||||
#include <QFrame>
|
||||
|
||||
#include "robomongo/core/utils/QtUtils.h"
|
||||
@@ -16,6 +18,15 @@
|
||||
#include "robomongo/core/settings/ConnectionSettings.h"
|
||||
#include "robomongo/core/settings/SshSettings.h"
|
||||
|
||||
namespace {
|
||||
const QString askPasswordText = "Ask for password each time";
|
||||
const QString askPassphraseText = "Ask for passphrase each time";
|
||||
bool isFileExists(const QString &path) {
|
||||
QFileInfo fileInfo(path);
|
||||
return fileInfo.exists() && fileInfo.isFile();
|
||||
}
|
||||
}
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
SshTunnelTab::SshTunnelTab(ConnectionSettings *settings) :
|
||||
@@ -26,12 +37,16 @@ namespace Robomongo
|
||||
_sshSupport->setStyleSheet("margin-bottom: 7px");
|
||||
_sshSupport->setChecked(info->enabled());
|
||||
|
||||
_askForPassword = new QCheckBox(askPasswordText);
|
||||
_askForPassword->setChecked(info->askPassword());
|
||||
VERIFY(connect(_askForPassword, SIGNAL(stateChanged(int)), this, SLOT(askForPasswordStateChanged(int))));
|
||||
|
||||
_sshHostName = new QLineEdit(QtUtils::toQString(info->host()));
|
||||
_userName = new QLineEdit(QtUtils::toQString(info->userName()));
|
||||
|
||||
_sshPort = new QLineEdit(QString::number(info->port()));
|
||||
_sshPort->setFixedWidth(80);
|
||||
QRegExp rx("\\d+");//(0-65554)
|
||||
_sshPort->setFixedWidth(40);
|
||||
QRegExp rx("\\d+"); //(0-65554)
|
||||
_sshPort->setValidator(new QRegExpValidator(rx, this));
|
||||
|
||||
_security = new QComboBox();
|
||||
@@ -103,6 +118,7 @@ namespace Robomongo
|
||||
connectionLayout->addWidget(_sshPassphraseLabel, 8, 0);
|
||||
connectionLayout->addWidget(_passphraseBox, 8, 1);
|
||||
connectionLayout->addWidget(_passphraseEchoModeButton, 8, 2);
|
||||
connectionLayout->addWidget(_askForPassword, 9, 1, 1, 2);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(_sshSupport);
|
||||
@@ -129,25 +145,48 @@ namespace Robomongo
|
||||
return _sshSupport->isChecked();
|
||||
}
|
||||
|
||||
void SshTunnelTab::sshSupportStateChange(int value)
|
||||
void SshTunnelTab::setPasswordFieldsEnabled(bool enabled)
|
||||
{
|
||||
_sshHostName->setEnabled(value);
|
||||
_userName->setEnabled(value);
|
||||
_sshPort->setEnabled(value);
|
||||
_security->setEnabled(value);
|
||||
_sshPassphraseLabel->setEnabled(enabled);
|
||||
_passphraseBox->setEnabled(enabled);
|
||||
_passwordBox->setEnabled(enabled);
|
||||
_passwordLabel->setEnabled(enabled);
|
||||
_passphraseEchoModeButton->setEnabled(enabled);
|
||||
_passwordEchoModeButton->setEnabled(enabled);
|
||||
}
|
||||
|
||||
_sshPrivateKeyLabel->setEnabled(value);
|
||||
_privateKeyBox->setEnabled(value);
|
||||
_selectPrivateFileButton->setEnabled(value);
|
||||
_sshAddressLabel->setEnabled(value);
|
||||
_sshUserNameLabel->setEnabled(value);
|
||||
_sshAuthMethodLabel->setEnabled(value);
|
||||
void SshTunnelTab::askForPasswordStateChanged(int state)
|
||||
{
|
||||
bool checked = state == Qt::Checked;
|
||||
if (checked) {
|
||||
_passphraseBox->setText("");
|
||||
_passwordBox->setText("");
|
||||
}
|
||||
|
||||
_sshPassphraseLabel->setEnabled(value);
|
||||
_passphraseBox->setEnabled(value);
|
||||
setPasswordFieldsEnabled(!checked && _sshSupport->isChecked());
|
||||
}
|
||||
|
||||
_passwordBox->setEnabled(value);
|
||||
_passwordLabel->setEnabled(value);
|
||||
void SshTunnelTab::sshSupportStateChange(int state)
|
||||
{
|
||||
bool checked = state == Qt::Checked;
|
||||
_sshHostName->setEnabled(checked);
|
||||
_userName->setEnabled(checked);
|
||||
_sshPort->setEnabled(checked);
|
||||
_security->setEnabled(checked);
|
||||
|
||||
_sshPrivateKeyLabel->setEnabled(checked);
|
||||
_privateKeyBox->setEnabled(checked);
|
||||
_selectPrivateFileButton->setEnabled(checked);
|
||||
_sshAddressLabel->setEnabled(checked);
|
||||
_sshUserNameLabel->setEnabled(checked);
|
||||
_sshAuthMethodLabel->setEnabled(checked);
|
||||
|
||||
_askForPassword->setEnabled(checked);
|
||||
|
||||
askForPasswordStateChanged(_askForPassword->checkState());
|
||||
|
||||
if (checked)
|
||||
_sshHostName->setFocus();
|
||||
}
|
||||
|
||||
void SshTunnelTab::securityChange(const QString& method)
|
||||
@@ -165,6 +204,7 @@ namespace Robomongo
|
||||
_passwordBox->setVisible(!isKey);
|
||||
_passwordLabel->setVisible(!isKey);
|
||||
_passwordEchoModeButton->setVisible(!isKey);
|
||||
_askForPassword->setText(isKey ? askPassphraseText : askPasswordText);
|
||||
}
|
||||
|
||||
void SshTunnelTab::setPrivateFile()
|
||||
@@ -196,24 +236,43 @@ namespace Robomongo
|
||||
// return SSHInfo::PASSWORD;
|
||||
// }
|
||||
|
||||
void SshTunnelTab::accept()
|
||||
bool SshTunnelTab::accept()
|
||||
{
|
||||
bool sshEnabled = _sshSupport->isChecked();
|
||||
QString authMethod = _security->currentText() == "Private Key" ? "publickey" : "password";
|
||||
|
||||
// Check for existence of the private key file name
|
||||
// and try to expand "~" character when needed
|
||||
QString privateKey = _privateKeyBox->text();
|
||||
if (sshEnabled && authMethod == "publickey" && !isFileExists(privateKey)) {
|
||||
bool failed = true;
|
||||
|
||||
// Try to expand "~" if available
|
||||
if (privateKey.startsWith ("~/")) {
|
||||
privateKey.replace (0, 1, QDir::homePath());
|
||||
if (isFileExists(privateKey)) {
|
||||
failed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
QString message = QString("Private key file \"%1\" doesn't exist").arg(privateKey);
|
||||
QMessageBox::information(this, "Settings are incomplete", message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SshSettings *info = _settings->sshSettings();
|
||||
info->setHost(QtUtils::toStdString(_sshHostName->text()));
|
||||
info->setPort(_sshPort->text().toInt());
|
||||
info->setUserName(QtUtils::toStdString(_userName->text()));
|
||||
info->setUserPassword(QtUtils::toStdString(_passwordBox->text()));
|
||||
// info->setPublicKeyFile("");
|
||||
info->setPrivateKeyFile(QtUtils::toStdString(_privateKeyBox->text()));
|
||||
info->setAskPassword(_askForPassword->isChecked());
|
||||
info->setPrivateKeyFile(QtUtils::toStdString(privateKey));
|
||||
info->setPassphrase(QtUtils::toStdString(_passphraseBox->text()));
|
||||
|
||||
if (_security->currentText() == "Private Key") {
|
||||
info->setAuthMethod("publickey");
|
||||
} else {
|
||||
info->setAuthMethod("password");
|
||||
}
|
||||
|
||||
info->setEnabled(_sshSupport->isChecked());
|
||||
info->setAuthMethod(QtUtils::toStdString(authMethod));
|
||||
info->setEnabled(sshEnabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SshTunnelTab::togglePasswordEchoMode()
|
||||
|
||||
@@ -23,21 +23,23 @@ namespace Robomongo
|
||||
|
||||
public:
|
||||
SshTunnelTab(ConnectionSettings *settings);
|
||||
void accept();
|
||||
bool accept();
|
||||
bool isSshSupported() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void sshSupportStateChange(int val);
|
||||
void sshSupportStateChange(int checked);
|
||||
void askForPasswordStateChanged(int checked);
|
||||
void securityChange(const QString& val);
|
||||
void setPrivateFile();
|
||||
void togglePasswordEchoMode();
|
||||
void togglePassphraseEchoMode();
|
||||
|
||||
private:
|
||||
// SSHInfo::SupportedAuthenticationMetods selectedAuthMethod();
|
||||
|
||||
void setPasswordFieldsEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
QCheckBox *_sshSupport;
|
||||
QCheckBox *_askForPassword;
|
||||
QLineEdit *_sshHostName;
|
||||
QLineEdit *_userName;
|
||||
QLineEdit *_sshPort;
|
||||
|
||||
@@ -33,12 +33,13 @@ namespace Robomongo
|
||||
_close->setIcon(QIcon(":/robomongo/icons/close_2_16x16.png"));
|
||||
_close->setToolButtonStyle(Qt::ToolButtonIconOnly);
|
||||
_close->setIconSize(QSize(16, 16));
|
||||
_close->hide(); // We do not need close button because ESC works
|
||||
|
||||
_findLine->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute);
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout();
|
||||
layout->setContentsMargins(6, 0, 6, 0);
|
||||
layout->setSpacing(4);
|
||||
layout->addWidget(_close);
|
||||
layout->setContentsMargins(2, 0, 6, 0);
|
||||
layout->setSpacing(7);
|
||||
layout->addWidget(_findLine);
|
||||
layout->addWidget(_next);
|
||||
layout->addWidget(_prev);
|
||||
@@ -50,8 +51,8 @@ namespace Robomongo
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout();
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->addWidget(_scin);
|
||||
mainLayout->addWidget(_findPanel);
|
||||
mainLayout->addWidget(_scin, 1);
|
||||
mainLayout->addWidget(_findPanel, 0, Qt::AlignBottom);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_findPanel->hide();
|
||||
@@ -71,14 +72,17 @@ namespace Robomongo
|
||||
bool isFocusScin = _scin->isActiveWindow();
|
||||
bool isShowFind = _findPanel->isVisible();
|
||||
if (Qt::Key_Escape == keyEvent->key() && isFocusScin && isShowFind) {
|
||||
// Hide & Show of Scintilla widget solves problem of UI blinking
|
||||
_scin->hide();
|
||||
_findPanel->hide();
|
||||
_scin->setFocus();
|
||||
_scin->show();
|
||||
return keyEvent->accept();
|
||||
} else if (Qt::Key_Return == keyEvent->key() && (keyEvent->modifiers() & Qt::ShiftModifier) && isFocusScin && isShowFind) {
|
||||
goToPrevElement();
|
||||
} else if (Qt::Key_Return == keyEvent->key() && isFocusScin && isShowFind) {
|
||||
goToNextElement();
|
||||
} else if (((keyEvent->modifiers() & Qt::ControlModifier) && keyEvent->key()==Qt::Key_F) && isFocusScin) {
|
||||
} else if (((keyEvent->modifiers() & Qt::ControlModifier) && keyEvent->key() == Qt::Key_F) && isFocusScin) {
|
||||
_findPanel->show();
|
||||
_findLine->setFocus();
|
||||
_findLine->selectAll();
|
||||
@@ -122,7 +126,7 @@ namespace Robomongo
|
||||
_scin->ensureCursorVisible();
|
||||
}
|
||||
else {
|
||||
QMessageBox::warning(this, tr("Search"),tr("The specified text was not found."));
|
||||
QMessageBox::warning(this, tr("Search"), tr("The specified text was not found."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Robomongo
|
||||
public:
|
||||
enum
|
||||
{
|
||||
HeightFindPanel = 40
|
||||
HeightFindPanel = 38
|
||||
};
|
||||
typedef QFrame BaseClass;
|
||||
explicit FindFrame(QWidget *parent);
|
||||
|
||||
@@ -155,13 +155,13 @@ namespace Robomongo
|
||||
}
|
||||
|
||||
if (((keyEvent->modifiers() & Qt::ControlModifier) &&
|
||||
(keyEvent->key()==Qt::Key_F4 || keyEvent->key()==Qt::Key_W ||
|
||||
keyEvent->key()==Qt::Key_T || keyEvent->key()==Qt::Key_Space ||
|
||||
keyEvent->key()==Qt::Key_F || keyEvent->key()==Qt::Key_Slash))
|
||||
(keyEvent->key() == Qt::Key_F4 || keyEvent->key() == Qt::Key_W ||
|
||||
keyEvent->key() == Qt::Key_T || keyEvent->key() == Qt::Key_Space ||
|
||||
keyEvent->key() == Qt::Key_F || keyEvent->key() == Qt::Key_Slash))
|
||||
|| keyEvent->key() == Qt::Key_Escape /*|| keyEvent->key() == Qt::Key_Return*/
|
||||
|| ((keyEvent->modifiers() & Qt::ControlModifier) && (keyEvent->modifiers() & Qt::AltModifier) && keyEvent->key()==Qt::Key_Left)
|
||||
|| ((keyEvent->modifiers() & Qt::ControlModifier) && (keyEvent->modifiers() & Qt::AltModifier) && keyEvent->key()==Qt::Key_Right)
|
||||
|| ((keyEvent->modifiers() & Qt::ControlModifier) && (keyEvent->modifiers() & Qt::ShiftModifier) && keyEvent->key()==Qt::Key_C)
|
||||
|| ((keyEvent->modifiers() & Qt::ControlModifier) && (keyEvent->modifiers() & Qt::AltModifier) && keyEvent->key() == Qt::Key_Left)
|
||||
|| ((keyEvent->modifiers() & Qt::ControlModifier) && (keyEvent->modifiers() & Qt::AltModifier) && keyEvent->key() == Qt::Key_Right)
|
||||
|| ((keyEvent->modifiers() & Qt::ControlModifier) && (keyEvent->modifiers() & Qt::ShiftModifier) && keyEvent->key() == Qt::Key_C)
|
||||
)
|
||||
{
|
||||
keyEvent->ignore();
|
||||
@@ -182,4 +182,18 @@ namespace Robomongo
|
||||
setMarginWidth(0, _lineNumberMarginWidth);
|
||||
}
|
||||
}
|
||||
|
||||
void RoboScintilla::setAppropriateBraceMatching() {
|
||||
#ifdef Q_OS_MAC
|
||||
// On Mac OS when brace matching is enabled, text
|
||||
// will blink when you move cursor to some brace or
|
||||
// when inside braces. This behaviour is not fully fixed
|
||||
// in QScintilla 2.9.1 and 2.8.4
|
||||
setBraceMatching(QsciScintilla::NoBraceMatch);
|
||||
#else
|
||||
setBraceMatching(QsciScintilla::StrictBraceMatch);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Robomongo
|
||||
void setIgnoreTabKey(bool ignore) { _ignoreTabKey = ignore; }
|
||||
int lineNumberMarginWidth() const;
|
||||
int textWidth(int style, const QString &text);
|
||||
void setAppropriateBraceMatching();
|
||||
|
||||
protected:
|
||||
void wheelEvent(QWheelEvent *e);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<file>icons/bson_object_16x16.png</file>
|
||||
<file>icons/database_16x16.png</file>
|
||||
<file>icons/loading.gif</file>
|
||||
<file>icons/loading_ticks_40x40.gif</file>
|
||||
<file>scripts/esprima.js</file>
|
||||
<file>icons/maximize.gif</file>
|
||||
<file>icons/text_16x16.png</file>
|
||||
@@ -38,8 +39,14 @@
|
||||
<file>icons/maximize_highlighted_16x16.png</file>
|
||||
<file>icons/table_16x16.png</file>
|
||||
<file>icons/table_highlighted_16x16.png</file>
|
||||
<file>icons/no_mark_16x16.png</file>
|
||||
<file>icons/yes_mark_16x16.png</file>
|
||||
<file>icons/no_mark_24x24.png</file>
|
||||
<file>icons/no_mark_24x24@2x.png</file>
|
||||
<file>icons/yes_mark_24x24.png</file>
|
||||
<file>icons/yes_mark_24x24@2x.png</file>
|
||||
<file>icons/skip_mark_24x24.png</file>
|
||||
<file>icons/skip_mark_24x24@2x.png</file>
|
||||
<file>icons/question_mark_24x24.png</file>
|
||||
<file>icons/question_mark_24x24@2x.png</file>
|
||||
<file>icons/time_16x16.png</file>
|
||||
<file>icons/key_16x16.png</file>
|
||||
<file>icons/progress_bar.gif</file>
|
||||
|
||||
|
After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 527 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
@@ -12,12 +12,12 @@ namespace Robomongo
|
||||
|
||||
int questionDialog(QWidget *parent, const QString &actionText, const QString &itemText, const QString& valueText)
|
||||
{
|
||||
return questionDialog(parent,actionText,itemText,textTemaple,valueText);
|
||||
return questionDialog(parent, actionText, itemText, textTemaple, valueText);
|
||||
}
|
||||
|
||||
int questionDialog(QWidget *parent, const QString &actionText, const QString &itemText, const QString &templateText, const QString &valueText)
|
||||
{
|
||||
return QMessageBox::question(parent,titleTemaple.arg(actionText).arg(itemText),templateText.arg(actionText).arg(itemText.toLower()).arg(valueText), QMessageBox::Yes, QMessageBox::No, QMessageBox::NoButton);
|
||||
return QMessageBox::question(parent, titleTemaple.arg(actionText).arg(itemText), templateText.arg(actionText).arg(itemText.toLower()).arg(valueText), QMessageBox::Yes, QMessageBox::No, QMessageBox::NoButton);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,12 +15,12 @@ namespace Robomongo
|
||||
{
|
||||
_logTextEdit->setReadOnly(true);
|
||||
_logTextEdit->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
VERIFY(connect(_logTextEdit,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(showContextMenu(const QPoint &))));
|
||||
VERIFY(connect(_logTextEdit, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint &))));
|
||||
QHBoxLayout *hlayout = new QHBoxLayout;
|
||||
hlayout->setContentsMargins(0,0,0,0);
|
||||
hlayout->setContentsMargins(0, 0, 0, 0);
|
||||
hlayout->addWidget(_logTextEdit);
|
||||
_clear = new QAction("Clear All", this);
|
||||
VERIFY(connect(_clear, SIGNAL(triggered()),_logTextEdit, SLOT(clear())));
|
||||
VERIFY(connect(_clear, SIGNAL(triggered()), _logTextEdit, SLOT(clear())));
|
||||
setLayout(hlayout);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace
|
||||
Robomongo::FindFrame *findFrame = new Robomongo::FindFrame(parent);
|
||||
findFrame->sciScintilla()->setLexer(javaScriptLexer);
|
||||
findFrame->sciScintilla()->setTabWidth(4);
|
||||
findFrame->sciScintilla()->setBraceMatching(QsciScintilla::StrictBraceMatch);
|
||||
findFrame->sciScintilla()->setAppropriateBraceMatching();
|
||||
findFrame->sciScintilla()->setFont(textFont);
|
||||
findFrame->sciScintilla()->setStyleSheet("QFrame {background-color: rgb(73, 76, 78); border: 1px solid #c7c5c4; border-radius: 4px; margin: 0px; padding: 0px;}");
|
||||
findFrame->sciScintilla()->setText(text);
|
||||
@@ -74,11 +74,11 @@ namespace
|
||||
namespace Robomongo
|
||||
{
|
||||
EditIndexDialog::EditIndexDialog(const EnsureIndexInfo &info, const QString &databaseName, const QString &serverAdress, QWidget *parent)
|
||||
:BaseClass(parent),_info(info)
|
||||
:BaseClass(parent), _info(info)
|
||||
{
|
||||
setWindowTitle("Index Properties");
|
||||
Indicator *serverIndicator = new Indicator(GuiRegistry::instance().serverIcon(), serverAdress);
|
||||
Indicator *collectionIndicator = new Indicator(GuiRegistry::instance().collectionIcon(),QtUtils::toQString(_info._collection.name()));
|
||||
Indicator *collectionIndicator = new Indicator(GuiRegistry::instance().collectionIcon(), QtUtils::toQString(_info._collection.name()));
|
||||
Indicator *databaseIndicator = new Indicator(GuiRegistry::instance().databaseIcon(), databaseName);
|
||||
|
||||
QHBoxLayout *hlayout = new QHBoxLayout;
|
||||
@@ -156,7 +156,7 @@ namespace Robomongo
|
||||
layout->addWidget(dropDupsHelpLabel, 7, 0, 1, 2);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
basicTab->setLayout(layout);
|
||||
VERIFY(connect(_uniqueCheckBox,SIGNAL(stateChanged(int)),this,SLOT(uniqueStateChanged(int))));
|
||||
VERIFY(connect(_uniqueCheckBox, SIGNAL(stateChanged(int)), this, SLOT(uniqueStateChanged(int))));
|
||||
return basicTab;
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace Robomongo
|
||||
_expireAfterLineEdit->setText(QString("%1").arg(_info._ttl));
|
||||
}
|
||||
expireStateChanged(expireCheckBox->checkState());
|
||||
VERIFY(connect(expireCheckBox,SIGNAL(stateChanged(int)),this,SLOT(expireStateChanged(int))));
|
||||
VERIFY(connect(expireCheckBox, SIGNAL(stateChanged(int)), this, SLOT(expireStateChanged(int))));
|
||||
|
||||
QLabel *sparseHelpLabel = createHelpLabel(
|
||||
"If set, the index only references documents with the specified field. "
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Robomongo
|
||||
HeightWidget = 320,
|
||||
WidthWidget = 480
|
||||
};
|
||||
explicit EditIndexDialog(const EnsureIndexInfo &info, const QString &databaseName, const QString &serverAdress, QWidget *parent=0);
|
||||
explicit EditIndexDialog(const EnsureIndexInfo &info, const QString &databaseName, const QString &serverAdress, QWidget *parent = 0);
|
||||
EnsureIndexInfo info() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
@@ -116,8 +116,8 @@ namespace Robomongo
|
||||
ExplorerCollectionTreeItem *par = dynamic_cast<ExplorerCollectionTreeItem *const>(parent());
|
||||
if (!par)
|
||||
return;
|
||||
EnsureIndexInfo fakeInfo(par->collection()->info(),"");
|
||||
EditIndexDialog dlg(fakeInfo , QtUtils::toQString(par->databaseItem()->database()->name()),QtUtils::toQString(par->databaseItem()->database()->server()->connectionRecord()->getFullAddress()), treeWidget());
|
||||
EnsureIndexInfo fakeInfo(par->collection()->info(), "");
|
||||
EditIndexDialog dlg(fakeInfo , QtUtils::toQString(par->databaseItem()->database()->name()), QtUtils::toQString(par->databaseItem()->database()->server()->connectionRecord()->getFullAddress()), treeWidget());
|
||||
int result = dlg.exec();
|
||||
if (result != QDialog::Accepted)
|
||||
return;
|
||||
@@ -126,7 +126,7 @@ namespace Robomongo
|
||||
if (!databaseTreeItem)
|
||||
return;
|
||||
|
||||
databaseTreeItem->enshureIndex(par,fakeInfo, dlg.info());
|
||||
databaseTreeItem->enshureIndex(par, fakeInfo, dlg.info());
|
||||
}
|
||||
|
||||
void ExplorerCollectionDirIndexesTreeItem::ui_reIndex()
|
||||
@@ -145,8 +145,8 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
|
||||
ExplorerCollectionIndexesTreeItem::ExplorerCollectionIndexesTreeItem(ExplorerCollectionDirIndexesTreeItem *parent,const EnsureIndexInfo &info)
|
||||
: BaseClass(parent),_info(info)
|
||||
ExplorerCollectionIndexesTreeItem::ExplorerCollectionIndexesTreeItem(ExplorerCollectionDirIndexesTreeItem *parent, const EnsureIndexInfo &info)
|
||||
: BaseClass(parent), _info(info)
|
||||
{
|
||||
QAction *deleteIndex = new QAction("Drop Index...", this);
|
||||
connect(deleteIndex, SIGNAL(triggered()), SLOT(ui_dropIndex()));
|
||||
@@ -163,7 +163,7 @@ namespace Robomongo
|
||||
void ExplorerCollectionIndexesTreeItem::ui_dropIndex()
|
||||
{
|
||||
// Ask user
|
||||
int answer = utils::questionDialog(treeWidget(),"Drop","Index",text(0));
|
||||
int answer = utils::questionDialog(treeWidget(), "Drop", "Index", text(0));
|
||||
|
||||
if (answer != QMessageBox::Yes)
|
||||
return;
|
||||
@@ -300,10 +300,10 @@ namespace Robomongo
|
||||
if (indexes.size() == 0)
|
||||
_indexDir->setExpanded(false);
|
||||
|
||||
for (std::vector<EnsureIndexInfo>::const_iterator it = indexes.begin(); it!=indexes.end(); ++it) {
|
||||
_indexDir->addChild(new ExplorerCollectionIndexesTreeItem(_indexDir,*it));
|
||||
for (std::vector<EnsureIndexInfo>::const_iterator it = indexes.begin(); it != indexes.end(); ++it) {
|
||||
_indexDir->addChild(new ExplorerCollectionIndexesTreeItem(_indexDir, *it));
|
||||
}
|
||||
_indexDir->setText(0, detail::buildName(ExplorerCollectionDirIndexesTreeItem::labelText,_indexDir->childCount()));
|
||||
_indexDir->setText(0, detail::buildName(ExplorerCollectionDirIndexesTreeItem::labelText, _indexDir->childCount()));
|
||||
}
|
||||
|
||||
void ExplorerCollectionTreeItem::handle(DeleteCollectionIndexResponse *event)
|
||||
@@ -351,7 +351,7 @@ namespace Robomongo
|
||||
QString ExplorerCollectionTreeItem::buildToolTip(MongoCollection *collection)
|
||||
{
|
||||
// This function does not used now
|
||||
char buff[2048]={0};
|
||||
char buff[2048] = {0};
|
||||
// sprintf(buff,tooltipTemplate,collection->name().c_str(),collection->info().count(),collection->sizeString().c_str());
|
||||
return buff;
|
||||
}
|
||||
@@ -429,7 +429,7 @@ namespace Robomongo
|
||||
void ExplorerCollectionTreeItem::ui_dropCollection()
|
||||
{
|
||||
// Ask user
|
||||
int answer = utils::questionDialog(treeWidget(),"Drop","collection",QtUtils::toQString(_collection->name()));
|
||||
int answer = utils::questionDialog(treeWidget(), "Drop", "collection", QtUtils::toQString(_collection->name()));
|
||||
|
||||
if (answer == QMessageBox::Yes) {
|
||||
MongoDatabase *database = _collection->database();
|
||||
@@ -530,7 +530,7 @@ namespace Robomongo
|
||||
openCurrentCollectionShell("getShardDistribution()");
|
||||
}
|
||||
|
||||
void ExplorerCollectionTreeItem::openCurrentCollectionShell(const QString &script, bool execute,const CursorPosition &cursor)
|
||||
void ExplorerCollectionTreeItem::openCurrentCollectionShell(const QString &script, bool execute, const CursorPosition &cursor)
|
||||
{
|
||||
QString query = detail::buildCollectionQuery(_collection->name(), script);
|
||||
AppRegistry::instance().app()->openShell(_collection->database(), query, execute, QtUtils::toQString(_collection->name()), cursor);
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Robomongo
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef ExplorerTreeItem BaseClass;
|
||||
ExplorerCollectionTreeItem(QTreeWidgetItem *parent,ExplorerDatabaseTreeItem *databaseItem,MongoCollection *collection);
|
||||
ExplorerCollectionTreeItem(QTreeWidgetItem *parent, ExplorerDatabaseTreeItem *databaseItem, MongoCollection *collection);
|
||||
MongoCollection *collection() const { return _collection; }
|
||||
void expand();
|
||||
void dropIndex(const QTreeWidgetItem * const ind);
|
||||
@@ -83,7 +83,7 @@ namespace Robomongo
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef ExplorerTreeItem BaseClass;
|
||||
explicit ExplorerCollectionIndexesTreeItem(ExplorerCollectionDirIndexesTreeItem *parent,const EnsureIndexInfo &info);
|
||||
explicit ExplorerCollectionIndexesTreeItem(ExplorerCollectionDirIndexesTreeItem *parent, const EnsureIndexInfo &info);
|
||||
|
||||
private Q_SLOTS:
|
||||
void ui_dropIndex();
|
||||
|
||||
@@ -26,8 +26,8 @@ namespace
|
||||
namespace Robomongo
|
||||
{
|
||||
|
||||
ExplorerDatabaseCategoryTreeItem::ExplorerDatabaseCategoryTreeItem(ExplorerDatabaseTreeItem *databaseItem,ExplorerDatabaseCategory category) :
|
||||
BaseClass(databaseItem) ,_category(category)
|
||||
ExplorerDatabaseCategoryTreeItem::ExplorerDatabaseCategoryTreeItem(ExplorerDatabaseTreeItem *databaseItem, ExplorerDatabaseCategory category) :
|
||||
BaseClass(databaseItem), _category(category)
|
||||
{
|
||||
if (_category == Collections) {
|
||||
QAction *createCollection = new QAction("Create Collection...", this);
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Robomongo
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef ExplorerTreeItem BaseClass;
|
||||
ExplorerDatabaseCategoryTreeItem(ExplorerDatabaseTreeItem *databaseItem,ExplorerDatabaseCategory category);
|
||||
ExplorerDatabaseCategoryTreeItem(ExplorerDatabaseTreeItem *databaseItem, ExplorerDatabaseCategory category);
|
||||
void expand();
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
void openCurrentDatabaseShell(Robomongo::MongoDatabase *database,const QString &script, bool execute = true, const Robomongo::CursorPosition &cursor = Robomongo::CursorPosition())
|
||||
void openCurrentDatabaseShell(Robomongo::MongoDatabase *database, const QString &script, bool execute = true, const Robomongo::CursorPosition &cursor = Robomongo::CursorPosition())
|
||||
{
|
||||
Robomongo::AppRegistry::instance().app()->openShell(database, script, execute, Robomongo::QtUtils::toQString(database->name()), cursor);
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace Robomongo
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
QString buildName(const QString& text,int count)
|
||||
QString buildName(const QString& text, int count)
|
||||
{
|
||||
if (count == -1)
|
||||
return QString("%1 ...").arg(text);
|
||||
@@ -42,7 +42,7 @@ namespace Robomongo
|
||||
return QString("%1 (%2)").arg(text).arg(count);
|
||||
}
|
||||
}
|
||||
ExplorerDatabaseTreeItem::ExplorerDatabaseTreeItem(QTreeWidgetItem *parent,MongoDatabase *const database) :
|
||||
ExplorerDatabaseTreeItem::ExplorerDatabaseTreeItem(QTreeWidgetItem *parent, MongoDatabase *const database) :
|
||||
BaseClass(parent),
|
||||
_database(database),
|
||||
_bus(AppRegistry::instance().bus()),
|
||||
@@ -84,17 +84,17 @@ namespace Robomongo
|
||||
setExpanded(false);
|
||||
setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
|
||||
|
||||
_collectionFolderItem = new ExplorerDatabaseCategoryTreeItem(this,Collections);
|
||||
_collectionFolderItem = new ExplorerDatabaseCategoryTreeItem(this, Collections);
|
||||
_collectionFolderItem->setText(0, "Collections");
|
||||
_collectionFolderItem->setIcon(0, GuiRegistry::instance().folderIcon());
|
||||
addChild(_collectionFolderItem);
|
||||
|
||||
_javascriptFolderItem = new ExplorerDatabaseCategoryTreeItem(this,Functions);
|
||||
_javascriptFolderItem = new ExplorerDatabaseCategoryTreeItem(this, Functions);
|
||||
_javascriptFolderItem->setText(0, "Functions");
|
||||
_javascriptFolderItem->setIcon(0, GuiRegistry::instance().folderIcon());
|
||||
addChild(_javascriptFolderItem);
|
||||
|
||||
_usersFolderItem = new ExplorerDatabaseCategoryTreeItem(this,Users);
|
||||
_usersFolderItem = new ExplorerDatabaseCategoryTreeItem(this, Users);
|
||||
_usersFolderItem->setText(0, "Users");
|
||||
_usersFolderItem->setIcon(0, GuiRegistry::instance().folderIcon());
|
||||
addChild(_usersFolderItem);
|
||||
@@ -122,12 +122,12 @@ namespace Robomongo
|
||||
|
||||
void ExplorerDatabaseTreeItem::enshureIndex(ExplorerCollectionTreeItem *const item, const EnsureIndexInfo &oldInfo, const EnsureIndexInfo &newInfo)
|
||||
{
|
||||
_bus->send(_database->server()->client(), new EnsureIndexRequest(item,oldInfo ,newInfo));
|
||||
_bus->send(_database->server()->client(), new EnsureIndexRequest(item, oldInfo, newInfo));
|
||||
}
|
||||
|
||||
void ExplorerDatabaseTreeItem::editIndexFromCollection(ExplorerCollectionTreeItem *const item,const std::string &oldIndexText,const std::string &newIndexText)
|
||||
void ExplorerDatabaseTreeItem::editIndexFromCollection(ExplorerCollectionTreeItem *const item, const std::string &oldIndexText, const std::string &newIndexText)
|
||||
{
|
||||
_bus->send(_database->server()->client(), new EditIndexRequest(item, item->collection()->info(),oldIndexText,newIndexText));
|
||||
_bus->send(_database->server()->client(), new EditIndexRequest(item, item->collection()->info(), oldIndexText, newIndexText));
|
||||
}
|
||||
|
||||
void ExplorerDatabaseTreeItem::expandFunctions()
|
||||
@@ -150,7 +150,7 @@ namespace Robomongo
|
||||
|
||||
std::vector<MongoCollection *> collections = event->collections;
|
||||
int count = collections.size();
|
||||
_collectionFolderItem->setText(0, detail::buildName("Collections",count));
|
||||
_collectionFolderItem->setText(0, detail::buildName("Collections", count));
|
||||
QtUtils::clearChildItems(_collectionFolderItem);
|
||||
|
||||
// Do not expand, when we do not have collections
|
||||
@@ -192,7 +192,7 @@ namespace Robomongo
|
||||
|
||||
std::vector<MongoUser> users = event->users();
|
||||
int count = users.size();
|
||||
_usersFolderItem->setText(0, detail::buildName("Users",count));
|
||||
_usersFolderItem->setText(0, detail::buildName("Users", count));
|
||||
|
||||
// Do not expand, when we do not have users
|
||||
if (count == 0)
|
||||
@@ -221,7 +221,7 @@ namespace Robomongo
|
||||
|
||||
std::vector<MongoFunction> functions = event->functions();
|
||||
int count = functions.size();
|
||||
_javascriptFolderItem->setText(0, detail::buildName("Functions",count));
|
||||
_javascriptFolderItem->setText(0, detail::buildName("Functions", count));
|
||||
|
||||
// Do not expand, when we do not have functions
|
||||
if (count == 0)
|
||||
@@ -237,22 +237,22 @@ namespace Robomongo
|
||||
|
||||
void ExplorerDatabaseTreeItem::handle(MongoDatabaseCollectionsLoadingEvent *event)
|
||||
{
|
||||
_collectionFolderItem->setText(0, detail::buildName("Collections",-1));
|
||||
_collectionFolderItem->setText(0, detail::buildName("Collections", -1));
|
||||
}
|
||||
|
||||
void ExplorerDatabaseTreeItem::handle(MongoDatabaseFunctionsLoadingEvent *event)
|
||||
{
|
||||
_javascriptFolderItem->setText(0, detail::buildName("Functions",-1));
|
||||
_javascriptFolderItem->setText(0, detail::buildName("Functions", -1));
|
||||
}
|
||||
|
||||
void ExplorerDatabaseTreeItem::handle(MongoDatabaseUsersLoadingEvent *event)
|
||||
{
|
||||
_usersFolderItem->setText(0, detail::buildName("Users",-1));
|
||||
_usersFolderItem->setText(0, detail::buildName("Users", -1));
|
||||
}
|
||||
|
||||
void ExplorerDatabaseTreeItem::addCollectionItem(MongoCollection *collection)
|
||||
{
|
||||
ExplorerCollectionTreeItem *collectionItem = new ExplorerCollectionTreeItem(_collectionFolderItem,this,collection);
|
||||
ExplorerCollectionTreeItem *collectionItem = new ExplorerCollectionTreeItem(_collectionFolderItem, this, collection);
|
||||
_collectionFolderItem->addChild(collectionItem);
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ namespace Robomongo
|
||||
|
||||
void ExplorerDatabaseTreeItem::ui_dbStatistics()
|
||||
{
|
||||
openCurrentDatabaseShell(_database,"db.stats()");
|
||||
openCurrentDatabaseShell(_database, "db.stats()");
|
||||
}
|
||||
|
||||
void ExplorerDatabaseTreeItem::ui_dbDrop()
|
||||
@@ -294,7 +294,7 @@ namespace Robomongo
|
||||
// Ask user
|
||||
QString buff = QString("Drop <b>%1</b> database?").arg(QtUtils::toQString(_database->name()));
|
||||
int answer = QMessageBox::question(treeWidget(),
|
||||
"Drop Database",buff,
|
||||
"Drop Database", buff,
|
||||
QMessageBox::Yes, QMessageBox::No, QMessageBox::NoButton);
|
||||
if (answer != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Robomongo
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
QString buildName(const QString& text,int count);
|
||||
QString buildName(const QString& text, int count);
|
||||
}
|
||||
|
||||
class ExplorerCollectionTreeItem;
|
||||
@@ -30,7 +30,7 @@ namespace Robomongo
|
||||
|
||||
public:
|
||||
typedef ExplorerTreeItem BaseClass;
|
||||
ExplorerDatabaseTreeItem(QTreeWidgetItem *parent,MongoDatabase *const database);
|
||||
ExplorerDatabaseTreeItem(QTreeWidgetItem *parent, MongoDatabase *const database);
|
||||
|
||||
MongoDatabase *database() const { return _database; }
|
||||
void expandCollections();
|
||||
@@ -39,7 +39,7 @@ namespace Robomongo
|
||||
void expandColection(ExplorerCollectionTreeItem *const item);
|
||||
void dropIndexFromCollection(ExplorerCollectionTreeItem *const item, const std::string &indexName);
|
||||
void enshureIndex(ExplorerCollectionTreeItem *const item, const EnsureIndexInfo &oldInfo, const EnsureIndexInfo &newInfo);
|
||||
void editIndexFromCollection(ExplorerCollectionTreeItem *const item,const std::string& oldIndexText,const std::string& newIndexText);
|
||||
void editIndexFromCollection(ExplorerCollectionTreeItem *const item, const std::string& oldIndexText, const std::string& newIndexText);
|
||||
|
||||
public Q_SLOTS:
|
||||
void handle(MongoDatabaseCollectionListLoadedEvent *event);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace Robomongo
|
||||
{
|
||||
|
||||
ExplorerFunctionTreeItem::ExplorerFunctionTreeItem(QTreeWidgetItem *parent,MongoDatabase *database, const MongoFunction &function) :
|
||||
ExplorerFunctionTreeItem::ExplorerFunctionTreeItem(QTreeWidgetItem *parent, MongoDatabase *database, const MongoFunction &function) :
|
||||
BaseClass(parent),
|
||||
_function(function),
|
||||
_database(database)
|
||||
@@ -64,7 +64,7 @@ namespace Robomongo
|
||||
void ExplorerFunctionTreeItem::ui_dropFunction()
|
||||
{
|
||||
// Ask user
|
||||
int answer = utils::questionDialog(treeWidget(),"Drop","Function",QtUtils::toQString(_function.name()));
|
||||
int answer = utils::questionDialog(treeWidget(), "Drop", "Function", QtUtils::toQString(_function.name()));
|
||||
|
||||
if (answer != QMessageBox::Yes)
|
||||
return;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Robomongo
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef ExplorerTreeItem BaseClass;
|
||||
ExplorerFunctionTreeItem(QTreeWidgetItem *parent,MongoDatabase *database, const MongoFunction &function);
|
||||
ExplorerFunctionTreeItem(QTreeWidgetItem *parent, MongoDatabase *database, const MongoFunction &function);
|
||||
MongoFunction function() const { return _function; }
|
||||
MongoDatabase *database() const { return _database; }
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
void openCurrentServerShell(Robomongo::MongoServer *const server,const QString &script, bool execute = true, const Robomongo::CursorPosition &cursor = Robomongo::CursorPosition())
|
||||
void openCurrentServerShell(Robomongo::MongoServer *const server, const QString &script, bool execute = true, const Robomongo::CursorPosition &cursor = Robomongo::CursorPosition())
|
||||
{
|
||||
Robomongo::AppRegistry::instance().app()->openShell(server, script, std::string(), execute, Robomongo::QtUtils::toQString(server->connectionRecord()->getReadableName()), cursor);
|
||||
}
|
||||
@@ -27,7 +27,7 @@ namespace
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
ExplorerServerTreeItem::ExplorerServerTreeItem(QTreeWidget *view,MongoServer *const server) : BaseClass(view),
|
||||
ExplorerServerTreeItem::ExplorerServerTreeItem(QTreeWidget *view, MongoServer *const server) : BaseClass(view),
|
||||
_server(server),
|
||||
_bus(AppRegistry::instance().bus())
|
||||
{
|
||||
@@ -102,12 +102,12 @@ namespace Robomongo
|
||||
MongoDatabase *database = dbs.at(i);
|
||||
|
||||
if (database->isSystem()) {
|
||||
ExplorerDatabaseTreeItem *dbItem = new ExplorerDatabaseTreeItem(systemFolder,database);
|
||||
ExplorerDatabaseTreeItem *dbItem = new ExplorerDatabaseTreeItem(systemFolder, database);
|
||||
systemFolder->addChild(dbItem);
|
||||
continue;
|
||||
}
|
||||
|
||||
ExplorerDatabaseTreeItem *dbItem = new ExplorerDatabaseTreeItem(this,database);
|
||||
ExplorerDatabaseTreeItem *dbItem = new ExplorerDatabaseTreeItem(this, database);
|
||||
addChild(dbItem);
|
||||
}
|
||||
|
||||
@@ -160,27 +160,27 @@ namespace Robomongo
|
||||
|
||||
void ExplorerServerTreeItem::ui_serverHostInfo()
|
||||
{
|
||||
openCurrentServerShell(_server,"db.hostInfo()");
|
||||
openCurrentServerShell(_server, "db.hostInfo()");
|
||||
}
|
||||
|
||||
void ExplorerServerTreeItem::ui_serverStatus()
|
||||
{
|
||||
openCurrentServerShell(_server,"db.serverStatus()");
|
||||
openCurrentServerShell(_server, "db.serverStatus()");
|
||||
}
|
||||
|
||||
void ExplorerServerTreeItem::ui_serverVersion()
|
||||
{
|
||||
openCurrentServerShell(_server,"db.version()");
|
||||
openCurrentServerShell(_server, "db.version()");
|
||||
}
|
||||
|
||||
void ExplorerServerTreeItem::ui_showLog()
|
||||
{
|
||||
openCurrentServerShell(_server,"show log");
|
||||
openCurrentServerShell(_server, "show log");
|
||||
}
|
||||
|
||||
void ExplorerServerTreeItem::ui_openShell()
|
||||
{
|
||||
openCurrentServerShell(_server,"");
|
||||
openCurrentServerShell(_server, "");
|
||||
}
|
||||
|
||||
void ExplorerServerTreeItem::ui_disconnectServer()
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Robomongo
|
||||
/*
|
||||
** Constructs ExplorerServerTreeItem
|
||||
*/
|
||||
ExplorerServerTreeItem(QTreeWidget *view,MongoServer *const server);
|
||||
ExplorerServerTreeItem(QTreeWidget *view, MongoServer *const server);
|
||||
|
||||
/*
|
||||
** Expand server tree item;
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
namespace Robomongo
|
||||
{
|
||||
ExplorerTreeItem::ExplorerTreeItem(QTreeWidgetItem *parent)
|
||||
:QObject(),BaseClass(parent),_contextMenu(new QMenu(treeWidget()) )
|
||||
:QObject(), BaseClass(parent), _contextMenu(new QMenu(treeWidget()) )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ExplorerTreeItem::ExplorerTreeItem(QTreeWidget *view)
|
||||
:QObject(view),BaseClass(view),_contextMenu(new QMenu(view) )
|
||||
:QObject(view), BaseClass(view), _contextMenu(new QMenu(view) )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -22,16 +22,16 @@ namespace
|
||||
|
||||
std::string buildToolTip(const Robomongo::MongoUser &user)
|
||||
{
|
||||
char buff[2048]={0};
|
||||
sprintf(buff,tooltipTemplate,user.name().c_str(),user.id().toString().c_str());
|
||||
char buff[2048] = {0};
|
||||
sprintf(buff, tooltipTemplate, user.name().c_str(), user.id().toString().c_str());
|
||||
return buff;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Robomongo
|
||||
{
|
||||
ExplorerUserTreeItem::ExplorerUserTreeItem(QTreeWidgetItem *parent,MongoDatabase *const database, const MongoUser &user) :
|
||||
BaseClass(parent),_user(user),_database(database)
|
||||
ExplorerUserTreeItem::ExplorerUserTreeItem(QTreeWidgetItem *parent, MongoDatabase *const database, const MongoUser &user) :
|
||||
BaseClass(parent), _user(user), _database(database)
|
||||
{
|
||||
QAction *dropUser = new QAction("Drop User", this);
|
||||
VERIFY(connect(dropUser, SIGNAL(triggered()), SLOT(ui_dropUser())));
|
||||
@@ -52,7 +52,7 @@ namespace Robomongo
|
||||
void ExplorerUserTreeItem::ui_dropUser()
|
||||
{
|
||||
// Ask user
|
||||
int answer = utils::questionDialog(treeWidget(),"Drop","User",QtUtils::toQString(_user.name()));
|
||||
int answer = utils::questionDialog(treeWidget(), "Drop", "User", QtUtils::toQString(_user.name()));
|
||||
|
||||
if (answer == QMessageBox::Yes) {
|
||||
_database->dropUser(_user.id());
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Robomongo
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef ExplorerTreeItem BaseClass;
|
||||
ExplorerUserTreeItem(QTreeWidgetItem *parent,MongoDatabase *const database, const MongoUser &user);
|
||||
ExplorerUserTreeItem(QTreeWidgetItem *parent, MongoDatabase *const database, const MongoUser &user);
|
||||
|
||||
private Q_SLOTS:
|
||||
void ui_dropUser();
|
||||
|
||||
@@ -89,9 +89,13 @@ namespace Robomongo
|
||||
|
||||
void ExplorerWidget::handle(ConnectionEstablishedEvent *event)
|
||||
{
|
||||
// Do not make UI changes for non PRIMARY connections
|
||||
if (event->connectionType != ConnectionPrimary)
|
||||
return;
|
||||
|
||||
decreaseProgress();
|
||||
|
||||
ExplorerServerTreeItem *item = new ExplorerServerTreeItem(_treeWidget,event->server);
|
||||
ExplorerServerTreeItem *item = new ExplorerServerTreeItem(_treeWidget, event->server);
|
||||
_treeWidget->addTopLevelItem(item);
|
||||
_treeWidget->setCurrentItem(item);
|
||||
_treeWidget->setFocus();
|
||||
|
||||
@@ -48,12 +48,12 @@ namespace Robomongo
|
||||
|
||||
QModelIndex BsonTableModelProxy::sibling(int row, int column, const QModelIndex &idx) const
|
||||
{
|
||||
return BaseClass::sibling(row,0,idx);
|
||||
return BaseClass::sibling(row, 0, idx);
|
||||
}
|
||||
|
||||
QModelIndex BsonTableModelProxy::index( int row, int col, const QModelIndex& parent ) const
|
||||
{
|
||||
BsonTreeItem *node = QtUtils::item<BsonTreeItem *>(sourceModel()->index(row,0,parent));
|
||||
BsonTreeItem *node = QtUtils::item<BsonTreeItem *>(sourceModel()->index(row, 0, parent));
|
||||
if (!node || _columns.size() <= col)
|
||||
return QModelIndex();
|
||||
|
||||
@@ -85,12 +85,12 @@ namespace Robomongo
|
||||
void BsonTableModelProxy::setSourceModel( QAbstractItemModel* model )
|
||||
{
|
||||
if (model) {
|
||||
BsonTreeItem *child = QtUtils::item<BsonTreeItem *>(model->index(0,0));
|
||||
BsonTreeItem *child = QtUtils::item<BsonTreeItem *>(model->index(0, 0));
|
||||
if (child) {
|
||||
_root = qobject_cast<BsonTreeItem *>(child->parent());
|
||||
if (_root) {
|
||||
int count = _root->childrenCount();
|
||||
for (int i=0; i < count; ++i) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
BsonTreeItem *child = _root->child(i);
|
||||
int countc = child->childrenCount();
|
||||
for (int j = 0; j < countc; ++j) {
|
||||
@@ -121,7 +121,7 @@ namespace Robomongo
|
||||
|
||||
if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
|
||||
bool isCut = node->type() == mongo::String || node->type() == mongo::Code || node->type() == mongo::CodeWScope;
|
||||
if (role == Qt::ToolTipRole){
|
||||
if (role == Qt::ToolTipRole) {
|
||||
result = isCut ? node->value() : node->value().left(500);
|
||||
}
|
||||
else{
|
||||
|
||||
@@ -18,10 +18,10 @@ namespace Robomongo
|
||||
explicit BsonTableModelProxy(QObject *parent = 0);
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
|
||||
int rowCount(const QModelIndex &parent=QModelIndex()) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
|
||||
QVariant headerData(int section,Qt::Orientation orientation, int role=Qt::DisplayRole) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
QModelIndex index( int row, int col, const QModelIndex& index ) const;
|
||||
virtual QModelIndex mapFromSource( const QModelIndex & sourceIndex ) const;
|
||||
virtual QModelIndex mapToSource( const QModelIndex &proxyIndex ) const;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace Robomongo
|
||||
{
|
||||
BsonTableView::BsonTableView(MongoShell *shell, const MongoQueryInfo &queryInfo, QWidget *parent)
|
||||
:BaseClass(parent),_notifier(this,shell,queryInfo)
|
||||
:BaseClass(parent), _notifier(this, shell, queryInfo)
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
@@ -68,7 +68,7 @@ namespace Robomongo
|
||||
QModelIndex selectedInd = selectedIndex();
|
||||
BsonTreeItem *documentItem = QtUtils::item<BsonTreeItem*>(selectedInd);
|
||||
QMenu menu(this);
|
||||
_notifier.initMenu(&menu,documentItem);
|
||||
_notifier.initMenu(&menu, documentItem);
|
||||
menu.exec(menuPoint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,9 @@ namespace
|
||||
const Robomongo::BsonTreeItem *findSuperRoot(const Robomongo::BsonTreeItem *const item)
|
||||
{
|
||||
Robomongo::BsonTreeItem *parent = qobject_cast<Robomongo::BsonTreeItem *>(item->parent());
|
||||
if(parent){
|
||||
if (parent) {
|
||||
Robomongo::BsonTreeItem *grParent = qobject_cast<Robomongo::BsonTreeItem *>(parent->parent());
|
||||
if(grParent){
|
||||
if (grParent) {
|
||||
return findSuperRoot(parent);
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ namespace Robomongo
|
||||
|
||||
BsonTreeItem* BsonTreeItem::childByKey(const QString &val)
|
||||
{
|
||||
for (unsigned i=0; i < _items.size(); ++i) {
|
||||
for (unsigned i = 0; i < _items.size(); ++i) {
|
||||
if (_items[i]->key() == val) {
|
||||
return _items[i];
|
||||
}
|
||||
@@ -102,7 +102,7 @@ namespace Robomongo
|
||||
|
||||
int BsonTreeItem::indexOf(BsonTreeItem *item) const
|
||||
{
|
||||
for (unsigned i=0; i < _items.size(); ++i) {
|
||||
for (unsigned i = 0; i < _items.size(); ++i) {
|
||||
if (item == _items[i]) {
|
||||
return i;
|
||||
}
|
||||
@@ -152,6 +152,6 @@ namespace Robomongo
|
||||
|
||||
void BsonTreeItem::removeChild(BsonTreeItem *item)
|
||||
{
|
||||
_items.erase(std::remove_if(_items.begin(), _items.end(), removeIfFound(item)),_items.end());
|
||||
_items.erase(std::remove_if(_items.begin(), _items.end(), removeIfFound(item)), _items.end());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ namespace Robomongo
|
||||
mongo::BSONObj root() const;
|
||||
mongo::BSONObj superRoot() const;
|
||||
|
||||
std::string fieldName() const { return _fieldName; };
|
||||
void setFieldName(const std::string &fieldName) { _fieldName = fieldName; };
|
||||
|
||||
QString key() const;
|
||||
void setKey(const QString &key);
|
||||
|
||||
@@ -66,5 +69,6 @@ namespace Robomongo
|
||||
const mongo::BSONObj _root;
|
||||
ChildContainerType _items;
|
||||
BsonItemFields _fields;
|
||||
std::string _fieldName;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -30,13 +30,16 @@ namespace
|
||||
{
|
||||
mongo::BSONElement element = iterator.next();
|
||||
BsonTreeItem *childItemInner = new BsonTreeItem(doc, root);
|
||||
QString fieldName = QtUtils::toQString(std::string(element.fieldName()));
|
||||
childItemInner->setKey(fieldName);
|
||||
std::string fieldName = std::string(element.fieldName());
|
||||
childItemInner->setFieldName(fieldName);
|
||||
|
||||
QString uiFieldName = QtUtils::toQString(fieldName);
|
||||
childItemInner->setKey(uiFieldName);
|
||||
|
||||
if (isArray) {
|
||||
// When we iterate array, show field names in square brackets
|
||||
// In this case field names are numeric, starting from 0.
|
||||
childItemInner->setKey("[" + fieldName + "]");
|
||||
childItemInner->setKey("[" + uiFieldName + "]");
|
||||
}
|
||||
|
||||
if (BsonUtils::isArray(element)) {
|
||||
@@ -98,7 +101,7 @@ namespace Robomongo
|
||||
{
|
||||
BsonTreeItem *node = QtUtils::item<BsonTreeItem*>(parent);
|
||||
if (node) {
|
||||
mongo::BSONElement elem = BsonUtils::indexOf(node->root(),parent.row());
|
||||
mongo::BSONElement elem = BsonUtils::indexOf(node->root(), parent.row());
|
||||
if (!elem.isNull() && elem.isABSONObj()) {
|
||||
parseDocument(node, elem.Obj(), elem.type() == mongo::Array);
|
||||
}
|
||||
@@ -162,11 +165,11 @@ namespace Robomongo
|
||||
|
||||
int col = index.column();
|
||||
|
||||
if(role == Qt::DecorationRole && col == BsonTreeItem::eKey ){
|
||||
if (role == Qt::DecorationRole && col == BsonTreeItem::eKey ) {
|
||||
return getIcon(node);
|
||||
}
|
||||
|
||||
if(role == Qt::TextColorRole && col == BsonTreeItem::eType){
|
||||
if (role == Qt::TextColorRole && col == BsonTreeItem::eType) {
|
||||
return QColor(Qt::gray);
|
||||
}
|
||||
|
||||
@@ -178,7 +181,7 @@ namespace Robomongo
|
||||
}
|
||||
else if (col == BsonTreeItem::eValue) {
|
||||
bool isCut = node->type() == mongo::String || node->type() == mongo::Code || node->type() == mongo::CodeWScope;
|
||||
if (role == Qt::ToolTipRole){
|
||||
if (role == Qt::ToolTipRole) {
|
||||
result = isCut ? node->value().left(500) : node->value();
|
||||
}
|
||||
else{
|
||||
@@ -186,7 +189,7 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
else if (col == BsonTreeItem::eType) {
|
||||
result = BsonUtils::BSONTypeToString(node->type(),node->binType(),AppRegistry::instance().settingsManager()->uuidEncoding());
|
||||
result = BsonUtils::BSONTypeToString(node->type(), node->binType(), AppRegistry::instance().settingsManager()->uuidEncoding());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +207,7 @@ namespace Robomongo
|
||||
|
||||
int BsonTreeModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
const BsonTreeItem *parentItem=NULL;
|
||||
const BsonTreeItem *parentItem = NULL;
|
||||
if (parent.isValid())
|
||||
parentItem = QtUtils::item<BsonTreeItem*>(parent);
|
||||
else
|
||||
@@ -235,7 +238,7 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::headerData(section,orientation,role);
|
||||
return BaseClass::headerData(section, orientation, role);
|
||||
}
|
||||
|
||||
QModelIndex BsonTreeModel::parent(const QModelIndex& index) const
|
||||
@@ -244,10 +247,10 @@ namespace Robomongo
|
||||
if (index.isValid()) {
|
||||
BsonTreeItem *const childItem = QtUtils::item<BsonTreeItem*const>(index);
|
||||
BsonTreeItem *const parentItem = static_cast<BsonTreeItem*const>(childItem->parent());
|
||||
if (parentItem && parentItem!=_root) {
|
||||
if (parentItem && parentItem != _root) {
|
||||
BsonTreeItem *const grandParent = static_cast<BsonTreeItem*const>(parentItem->parent());
|
||||
int row = grandParent->indexOf(parentItem);
|
||||
result= createIndex(row, 0, parentItem);
|
||||
result = createIndex(row, 0, parentItem);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -257,7 +260,7 @@ namespace Robomongo
|
||||
{
|
||||
QModelIndex index;
|
||||
if (hasIndex(row, column, parent)) {
|
||||
const BsonTreeItem * parentItem=NULL;
|
||||
const BsonTreeItem * parentItem = NULL;
|
||||
if (!parent.isValid()) {
|
||||
parentItem = _root;
|
||||
} else {
|
||||
@@ -274,9 +277,9 @@ namespace Robomongo
|
||||
|
||||
void BsonTreeModel::insertItem(BsonTreeItem *parent, BsonTreeItem *children)
|
||||
{
|
||||
QModelIndex index = createIndex(0,0,parent);
|
||||
QModelIndex index = createIndex(0, 0, parent);
|
||||
unsigned child_count = parent->childrenCount();
|
||||
beginInsertRows(index,child_count,child_count);
|
||||
beginInsertRows(index, child_count, child_count);
|
||||
parent->addChild(children);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
@@ -14,15 +14,15 @@ namespace Robomongo
|
||||
public:
|
||||
typedef QAbstractItemModel BaseClass;
|
||||
static const QIcon &getIcon(BsonTreeItem *item);
|
||||
explicit BsonTreeModel(const std::vector<MongoDocumentPtr> &documents,QObject *parent = 0);
|
||||
explicit BsonTreeModel(const std::vector<MongoDocumentPtr> &documents, QObject *parent = 0);
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
|
||||
int rowCount(const QModelIndex &parent=QModelIndex()) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
|
||||
QVariant headerData(int section,Qt::Orientation orientation, int role=Qt::DisplayRole) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex &parent= QModelIndex()) const;
|
||||
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
|
||||
virtual QModelIndex parent(const QModelIndex& index) const;
|
||||
|
||||
void insertItem(BsonTreeItem *parent, BsonTreeItem *children);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
namespace Robomongo
|
||||
{
|
||||
BsonTreeView::BsonTreeView(MongoShell *shell, const MongoQueryInfo &queryInfo, QWidget *parent)
|
||||
: BaseClass(parent),_notifier(this,shell,queryInfo)
|
||||
: BaseClass(parent), _notifier(this, shell, queryInfo)
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
setAttribute(Qt::WA_MacShowFocusRect, false);
|
||||
@@ -70,7 +70,7 @@ namespace Robomongo
|
||||
}
|
||||
}
|
||||
|
||||
_notifier.initMenu(&menu,documentItem);
|
||||
_notifier.initMenu(&menu, documentItem);
|
||||
menu.exec(menuPoint);
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,7 @@ namespace Robomongo
|
||||
{
|
||||
QModelIndexList indexes = selectedIndexes();
|
||||
if (detail::isMultiSelection(indexes)) {
|
||||
for (int i=0; i<indexes.count(); ++i)
|
||||
for (int i = 0; i<indexes.count(); ++i)
|
||||
expandNode(indexes[i]);
|
||||
} else {
|
||||
expandNode(selectedIndex());
|
||||
@@ -148,7 +148,7 @@ namespace Robomongo
|
||||
{
|
||||
QModelIndexList indexes = selectedIndexes();
|
||||
if (detail::isMultiSelection(indexes)) {
|
||||
for (int i=0; i<indexes.count(); ++i)
|
||||
for (int i = 0; i<indexes.count(); ++i)
|
||||
collapseNode(indexes[i]);
|
||||
} else {
|
||||
collapseNode(selectedIndex());
|
||||
|
||||