# # # add_file "res/forms/dialogs/source_picker.ui" # content [fc61df06d53748792a7e655e18140614ca2b4b4e] # # add_file "src/view/dialogs/SourcePicker.cpp" # content [5cb8db11e0b9d8f20a36dcef9de1f0761f4c8c9e] # # add_file "src/view/dialogs/SourcePicker.h" # content [631d7998979f12f1ced980147f6bbdb778113902] # # patch "sources.pri" # from [41d8ea59039763d8848a4e8341c8a8b5beacf41b] # to [44e57545b5c69a8a7622c007b97d13be5f5b1867] # # patch "src/GuitoneStandalone.cpp" # from [2f030462cb9f3b2149c007887525f27d37564aec] # to [71636aba9f994c85f0ddbbea31ee236f3b7de871] # # patch "src/monotone/MonotoneHandle.cpp" # from [f73ac1b2215cefb68bd5f67dbf8e81df2593c40a] # to [86f796134ef0dacf87dcd9ab5b661c4e21f32bce] # # patch "src/monotone/MonotoneHandle.h" # from [bb4a37a2bc3a467700d4ba9728ad168dd5e80d05] # to [77be272ea7291102c6d439e36f2aef180de5e2b5] # # patch "src/view/dialogs/DialogManager.cpp" # from [bd49f34e0464d9f62c68aebc1f48dc87d19213b7] # to [1b55f1990fc3b7657fa1650c513b4544912bc9eb] # # patch "src/view/dialogs/DialogManager.h" # from [b01576f62dbfa6bb5b7d921b8d06ed2f3e0ddadb] # to [c3d0af32b9678790ab5f4d7e1d9a234fdcacf45c] # # patch "src/view/dialogs/OpenPrompt.cpp" # from [eebc742dce8d55bad628ab33f1a5c2ece399adc0] # to [66b827151457bee77f07dde675514838a1279be1] # ============================================================ --- res/forms/dialogs/source_picker.ui fc61df06d53748792a7e655e18140614ca2b4b4e +++ res/forms/dialogs/source_picker.ui fc61df06d53748792a7e655e18140614ca2b4b4e @@ -0,0 +1,233 @@ + + + SourcePicker + + + + 0 + 0 + 541 + 323 + + + + + 0 + 0 + + + + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Horizontal + + + + + 0 + 0 + + + + + 150 + 16777215 + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::DropOnly + + + false + + + false + + + false + + + + Places + + + + + + + 0 + 200 + + + + QAbstractItemView::NoEditTriggers + + + false + + + true + + + QAbstractItemView::DragOnly + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + + + + + + 0 + 0 + + + + + + + Host + + + + + + + mtn:// + + + + + + + Key + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + SizeableLabel { + qproperty-relativeSize: 0.85; + color: red; +} + + + + + + true + + + 5 + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + SizeableLabel + QLabel +
SizeableLabel.h
+
+
+ + + + buttonBox + accepted() + SourcePicker + accept() + + + 222 + 328 + + + 157 + 274 + + + + + buttonBox + rejected() + SourcePicker + reject() + + + 290 + 334 + + + 286 + 274 + + + + +
============================================================ --- src/view/dialogs/SourcePicker.cpp 5cb8db11e0b9d8f20a36dcef9de1f0761f4c8c9e +++ src/view/dialogs/SourcePicker.cpp 5cb8db11e0b9d8f20a36dcef9de1f0761f4c8c9e @@ -0,0 +1,180 @@ +/*************************************************************************** + * Copyright (C) 2010 by Thomas Keller * + * address@hidden * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#include "SourcePicker.h" +#include "MonotoneUtil.h" + +#include +#include +#include + +SourcePicker::SourcePicker(QWidget * parent) : Dialog(parent) +{ + setupUi(this); + Dialog::init(); + + serverAddress->setValidator(new QRegExpValidator( + QRegExp("^mtn://([\\w\\-]+(\\.[\\w\\-]+)*(:\\d+)?)$"), + this + )); + + fsModel = new QFileSystemModel(this); + fileBrowser->setModel(fsModel); + + QFileInfoList drives = QDir::drives(); + I(drives.size() > 0); + + foreach (const QFileInfo & drive, drives) + { + QString path = drive.absoluteFilePath(); + QTreeWidgetItem * item = new QTreeWidgetItem(places); + item->setData(0, Qt::UserRole, path); + item->setData(0, Qt::DecorationRole, + fsModel->iconProvider()->icon(drive)); + + if (path == "/") + item->setData(0, Qt::DisplayRole, tr("root directory")); + else + item->setData(0, Qt::DisplayRole, tr("drive %1").arg(path.left(2))); + + places->addTopLevelItem(item); + } + + QTreeWidgetItem * item = new QTreeWidgetItem(places); + item->setData(0, Qt::UserRole, QDir::homePath()); + item->setData(0, Qt::DisplayRole, tr("home")); + item->setData(0, Qt::DecorationRole, + fsModel->iconProvider()->icon(QFileIconProvider::Folder)); + places->addTopLevelItem(item); + + QString initialPath = drives.at(0).absoluteFilePath(); + fsModel->setRootPath(initialPath); + QModelIndex rootIndex = fsModel->index(initialPath); + fileBrowser->setRootIndex(rootIndex); + + connect( + places, SIGNAL(itemClicked(QTreeWidgetItem *, int)), + this, SLOT(placesClicked(QTreeWidgetItem *, int)) + ); + + connect( + fileBrowser, SIGNAL(clicked(const QModelIndex &)), + this, SLOT(fileBrowserClicked(const QModelIndex &)) + ); + + // FIXME: Qt's column view has no sane default for new columns in a + // QColumnView - so we set one. And btw, no, there is no + // "setDefaultColumnWidth()" function... + int width = (fileBrowser->sizeHint().rwidth() / 2); + QList colWidths; + for (int i=0; i<50; ++i) + colWidths.append(width); + fileBrowser->setColumnWidths(colWidths); +} + +SourcePicker::~SourcePicker() {} + +void SourcePicker::init(const MonotoneHandle::Type & type) +{ + validationMessage->setText(QString()); + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + + if (type == MonotoneHandle::workspace_handle) + { + setWindowTitle(tr("Open a workspace")); + groupBox->setTitle(tr("Please select a workspace directory")); + } + else + if (type == MonotoneHandle::database_handle) + { + setWindowTitle(tr("Open a database")); + groupBox->setTitle(tr("Please select a database file")); + } + else + { + setWindowTitle(tr("Connect to a remote server")); + groupBox->setTitle(tr("Please select the host address and " + "key for authentication")); + } + + if (type == MonotoneHandle::server_handle) + { + privateKeys->clear(); + privateKeys->addItem(tr(""), QString()); + + QMap keys = + MonotoneUtil::getPrivateKeyMap(MonotoneHandle::create()); + + QMapIterator it(keys); + while (it.hasNext()) + { + it.next(); + privateKeys->addItem(it.value(), it.key()); + } + + fileWidget->hide(); + serverWidget->show(); + } + else + { + if (type == MonotoneHandle::workspace_handle) + { + fsModel->setNameFilters(QStringList()); + fsModel->setFilter(QDir::Drives | QDir::AllDirs | QDir::NoDotAndDotDot); + } + else + { + fsModel->setNameFilters(QStringList() << "*.db" << "*.mtn"); + fsModel->setFilter(QDir::AllEntries | QDir::NoDotAndDotDot); + } + + fileWidget->show(); + serverWidget->hide(); + } +} + +void SourcePicker::placesClicked(QTreeWidgetItem * item, int column) +{ + QString path = item->data(column, Qt::UserRole).toString(); + fsModel->setRootPath(path); + QModelIndex newRootIndex = fsModel->index(path); + fileBrowser->setRootIndex(newRootIndex); +} + +void SourcePicker::fileBrowserClicked(const QModelIndex & index) +{ + // ignore disabled items + if ((index.flags() & Qt::ItemIsEnabled) != Qt::ItemIsEnabled) + return; + + QString path = fsModel->fileInfo(index).absoluteFilePath(); + try + { + MonotoneHandlePtr handle = MonotoneHandle::create(path); + } + catch (GuitoneException & e) + { + validationMessage->setText(e.what()); + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + return; + } + + validationMessage->setText(QString()); + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); +} + ============================================================ --- src/view/dialogs/SourcePicker.h 631d7998979f12f1ced980147f6bbdb778113902 +++ src/view/dialogs/SourcePicker.h 631d7998979f12f1ced980147f6bbdb778113902 @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2010 by Thomas Keller * + * address@hidden * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#ifndef SOURCEPICKER_H +#define SOURCEPICKER_H + +#include "ui_source_picker.h" +#include "Dialog.h" +#include "vocab.h" + +#include +#include + +class SourcePicker : public Dialog, private Ui::SourcePicker +{ + Q_OBJECT + +public: + SourcePicker(QWidget *); + ~SourcePicker(); + + void init(const MonotoneHandle::Type &); + +signals: + void sourceSelected(const MonotoneHandlePtr &); + +private slots: + void placesClicked(QTreeWidgetItem *, int); + void fileBrowserClicked(const QModelIndex &); + +private: + QFileSystemModel * fsModel; + +}; + +#endif + ============================================================ --- sources.pri 41d8ea59039763d8848a4e8341c8a8b5beacf41b +++ sources.pri 44e57545b5c69a8a7622c007b97d13be5f5b1867 @@ -57,6 +57,7 @@ HEADERS = src/view/widgets/TreeView.h \ src/view/dialogs/Message.h \ src/view/dialogs/AnnotateFile.h \ src/view/dialogs/CreateCert.h \ + src/view/dialogs/SourcePicker.h \ src/view/panels/IconHelp.h \ src/view/panels/DatabaseVariables.h \ src/view/panels/NodeInfo.h \ @@ -161,6 +162,7 @@ SOURCES += src/view/widgets/TreeView.cpp src/view/dialogs/Message.cpp \ src/view/dialogs/AnnotateFile.cpp \ src/view/dialogs/CreateCert.cpp \ + src/view/dialogs/SourcePicker.cpp \ src/view/panels/IconHelp.cpp \ src/view/panels/DatabaseVariables.cpp \ src/view/panels/NodeInfo.cpp \ @@ -239,6 +241,8 @@ FORMS += res/forms/dialogs/select_revi res/forms/dialogs/new_project_setup.ui \ res/forms/dialogs/annotate.ui \ res/forms/dialogs/create_cert.ui \ + res/forms/dialogs/source_picker.ui \ res/forms/panels/icon_help.ui \ res/forms/panels/db_variables.ui \ res/forms/panels/nodeinfo.ui + ============================================================ --- src/GuitoneStandalone.cpp 2f030462cb9f3b2149c007887525f27d37564aec +++ src/GuitoneStandalone.cpp 71636aba9f994c85f0ddbbea31ee236f3b7de871 @@ -192,6 +192,11 @@ void GuitoneStandalone::load(const QStri { MonotoneHandlePtr handle = MonotoneHandle::create(pathOrURI); + if (handle->getType() == MonotoneHandle::empty_handle) + { + throw new GuitoneException(tr("Source was empty")); + } + switch (handle->getType()) { case MonotoneHandle::database_handle: ============================================================ --- src/monotone/MonotoneHandle.cpp f73ac1b2215cefb68bd5f67dbf8e81df2593c40a +++ src/monotone/MonotoneHandle.cpp 86f796134ef0dacf87dcd9ab5b661c4e21f32bce @@ -23,6 +23,8 @@ #include #include +QStringList MonotoneHandle::defaultDatabaseLocations; + MonotoneHandle::MonotoneHandle(const QString & d, Type t) : data(d), type(t) {} void MonotoneHandle::validateDatabaseFile(const QString & database) @@ -163,29 +165,35 @@ void MonotoneHandle::resolveDatabaseAlia { QString alias = rx.cap(1); - QString output; - QStringList args; - args << "au" << "lua" - << "get_default_database_locations"; - - if (MonotoneProcess::singleRun(args, MonotoneHandlePtr(), output)) + if (defaultDatabaseLocations.size() == 0) { - QRegExp rx("\\[\\d+\\] = \"([^\"]+)\";"); + QString output; + QStringList args; + args << "au" << "lua" + << "get_default_database_locations"; - int pos = 0; - while ((pos = rx.indexIn(output, pos)) != -1) - { - pos += rx.matchedLength(); - QString location = rx.cap(1); + if (MonotoneProcess::singleRun(args, MonotoneHandlePtr(), output)) + { + QRegExp rx("\\[\\d+\\] = \"([^\"]+)\";"); - QFileInfo finfo(location + "/" + alias); - if (finfo.isFile()) + int pos = 0; + while ((pos = rx.indexIn(output, pos)) != -1) { - database = finfo.canonicalFilePath(); - break; + pos += rx.matchedLength(); + defaultDatabaseLocations.append(rx.cap(1)); } + } + } + + foreach (const QString & defaultLocation, defaultDatabaseLocations) + { + QFileInfo finfo(defaultLocation + "/" + alias); + if (finfo.isFile()) + { + database = finfo.canonicalFilePath(); + break; } - } + } } } @@ -193,43 +201,46 @@ MonotoneHandlePtr MonotoneHandle::create { QString cleanedPathOrURI(pathOrURI.trimmed()); - if (cleanedPathOrURI.isEmpty()) - { - throw GuitoneException(QObject::tr("Path / URI is empty")); - } - Type type; - QRegExp rx("^mtn://([\\w\\-]+(?:\\.[\\w\\-]+)*(?::\\d+)?)$"); - if (rx.indexIn(cleanedPathOrURI) != -1) + if (cleanedPathOrURI.isEmpty()) { - validateServerConnection(rx.cap(1)); - type = server_handle; + type = empty_handle; } else { - QFileInfo finfo(cleanedPathOrURI); - if (finfo.isDir()) + QRegExp rx("^mtn://([\\w\\-]+(?:\\.[\\w\\-]+)*(?::\\d+)?)$"); + if (rx.indexIn(cleanedPathOrURI) != -1) { - cleanedPathOrURI = finfo.canonicalFilePath(); - - QString database; - validateWorkspacePath(cleanedPathOrURI, database); - resolveDatabaseAlias(database); - validateDatabaseFile(database); - - type = workspace_handle; + validateServerConnection(rx.cap(1)); + type = server_handle; } else { - resolveDatabaseAlias(cleanedPathOrURI); - validateDatabaseFile(cleanedPathOrURI); + QFileInfo finfo(cleanedPathOrURI); + if (finfo.isDir()) + { + cleanedPathOrURI = finfo.canonicalFilePath(); - type = database_handle; + QString database; + validateWorkspacePath(cleanedPathOrURI, database); + resolveDatabaseAlias(database); + validateDatabaseFile(database); + + type = workspace_handle; + } + else + { + resolveDatabaseAlias(cleanedPathOrURI); + validateDatabaseFile(cleanedPathOrURI); + + type = database_handle; + } } + + I(!cleanedPathOrURI.isEmpty()); } - I(!cleanedPathOrURI.isEmpty()); return MonotoneHandlePtr(new MonotoneHandle(cleanedPathOrURI, type)); } ============================================================ --- src/monotone/MonotoneHandle.h bb4a37a2bc3a467700d4ba9728ad168dd5e80d05 +++ src/monotone/MonotoneHandle.h 77be272ea7291102c6d439e36f2aef180de5e2b5 @@ -24,13 +24,16 @@ public: class MonotoneHandle { public: - typedef enum { workspace_handle = 1, database_handle, server_handle } Type; + typedef enum { empty_handle = 1, + workspace_handle, + database_handle, + server_handle } Type; Type getType() const { return type; } QString getData() const { return data; } QString identify() const { return QString("%1:%2").arg((int)type).arg(data); } - static MonotoneHandlePtr create(const QString &); + static MonotoneHandlePtr create(const QString & handle = QString()); private: QString data; @@ -43,6 +46,7 @@ private: static void validateServerConnection(const QString &); static void resolveDatabaseAlias(QString &); + static QStringList defaultDatabaseLocations; }; #endif ============================================================ --- src/view/dialogs/DialogManager.cpp bd49f34e0464d9f62c68aebc1f48dc87d19213b7 +++ src/view/dialogs/DialogManager.cpp 1b55f1990fc3b7657fa1650c513b4544912bc9eb @@ -21,7 +21,7 @@ DialogManager::DialogManager(QWidget * p DialogManager::DialogManager(QWidget * parentWidget) : QObject(parentWidget), about(0), preferences(0), - createDatabase(0), changeKeyPassword(0) + createDatabase(0), changeKeyPassword(0), sourcePicker(0) {} DialogManager::~DialogManager() @@ -30,6 +30,7 @@ DialogManager::~DialogManager() if (preferences) delete preferences; if (createDatabase) delete createDatabase; if (changeKeyPassword) delete changeKeyPassword; + if (sourcePicker) delete sourcePicker; } QWidget * DialogManager::parentWidget() const @@ -42,6 +43,7 @@ void DialogManager::closeAllDialogs() if (about) about->close(); if (preferences) preferences->close(); if (createDatabase) createDatabase->close(); + if (sourcePicker) sourcePicker->close(); emit allDialogsClosed(); } @@ -93,6 +95,17 @@ void DialogManager::showChangeKeyPasswor showDialog(changeKeyPassword); } +void DialogManager::showSourcePicker(const MonotoneHandle::Type & type) +{ + if (!sourcePicker) + { + sourcePicker = new SourcePicker(parentWidget()); + } + + sourcePicker->init(type); + showDialog(sourcePicker); +} + void DialogManager::showDialog(Dialog * dlg) { if (!openDialogs.contains(dlg)) ============================================================ --- src/view/dialogs/DialogManager.h b01576f62dbfa6bb5b7d921b8d06ed2f3e0ddadb +++ src/view/dialogs/DialogManager.h c3d0af32b9678790ab5f4d7e1d9a234fdcacf45c @@ -23,6 +23,8 @@ #include "Preferences.h" #include "CreateDatabase.h" #include "ChangeKeyPassword.h" +#include "SourcePicker.h" + #include "vocab.h" #include @@ -41,6 +43,7 @@ public slots: void showPreferences(); void showCreateDatabase(); void showChangeKeyPassword(const QString &); + void showSourcePicker(const MonotoneHandle::Type &); signals: void databaseCreated(const QString &); @@ -55,6 +58,7 @@ protected: Preferences * preferences; CreateDatabase * createDatabase; ChangeKeyPassword * changeKeyPassword; + SourcePicker * sourcePicker; private: void cleanup(); ============================================================ --- src/view/dialogs/OpenPrompt.cpp eebc742dce8d55bad628ab33f1a5c2ece399adc0 +++ src/view/dialogs/OpenPrompt.cpp 66b827151457bee77f07dde675514838a1279be1 @@ -106,47 +106,17 @@ void OpenPrompt::openDatabase() void OpenPrompt::openDatabase() { - QString fn = QFileDialog::getOpenFileName( - this, - tr("Select your database..."), - QString(), - tr("monotone Databases (*.mtn *.handle)") - ); - - if (fn.isEmpty()) return; - setEnabled(false); - setDisabled(true); - emit loadDatabase(fn); + dialogManager->showSourcePicker(MonotoneHandle::database_handle); } void OpenPrompt::openWorkspace() { - QString fn = QFileDialog::getExistingDirectory( - this, - tr("Select your workspace...") - ); - - if (fn.isEmpty()) - return; - - setDisabled(true); - emit loadWorkspace(fn); + dialogManager->showSourcePicker(MonotoneHandle::workspace_handle); } void OpenPrompt::newServerConnection() { - bool ok; - QString connection = QInputDialog::getText( - this, - tr("Enter a new server connection"), - tr("Please enter a new server connection (f.e. mtn://my.server.com:4691):"), - QLineEdit::Normal, "mtn://", &ok).trimmed(); - - if (!ok || connection.isEmpty()) - return; - - setDisabled(true); - emit connectToServer(connection); + dialogManager->showSourcePicker(MonotoneHandle::server_handle); } void OpenPrompt::recentWorkspacesChanged(int idx)