# # # delete "res/forms/dialogs/source_picker.ui" # # delete "src/view/dialogs/SourcePicker.cpp" # # delete "src/view/dialogs/SourcePicker.h" # # add_file "res/forms/dialogs/connect_server.ui" # content [970d0f720ca5aef9e50ede7162e0604fa88a10df] # # add_file "src/view/dialogs/ConnectServerDialog.cpp" # content [a4efba6c7ac92f367fed5fea02f461d2313f2e00] # # add_file "src/view/dialogs/ConnectServerDialog.h" # content [8d2149ca291420b113b30a054be41bc1990c198e] # # add_file "src/view/dialogs/FileDialog.cpp" # content [6d9fb7fb22ab2735f9bd860074ca7941a7b500de] # # add_file "src/view/dialogs/FileDialog.h" # content [470760cd190923eca54967c9a357a8376197ce9f] # # patch "sources.pri" # from [44e57545b5c69a8a7622c007b97d13be5f5b1867] # to [2ab63afc8aff74062cfe2afea515d0f6e6ed2c64] # # patch "src/view/dialogs/DialogManager.cpp" # from [35f72fd35f216759ced9c232dfd6f618bdc255bd] # to [d7365a29a00859e3bd859b7c0772cd1951ee8780] # # patch "src/view/dialogs/DialogManager.h" # from [e9a0ddda832900391b7edd4f182d144a675d74e7] # to [343b2372939ed1dbe4fc6de062a1041204b756de] # # patch "src/view/dialogs/OpenPrompt.cpp" # from [7140354d40e226daa36a809362cbebbfbf644a85] # to [feb81552935435e828076c6024187ce978321316] # # patch "src/view/mainwindows/ServerWindow.cpp" # from [95e24fe707f9002af347269a4d0b590374a22a7e] # to [b946fbbaeb71f07104d63d3a0a52c0590a3e11c6] # # patch "src/view/widgets/MenuBar.cpp" # from [24674587777e567a8b9ca191db096e1cc777ddd5] # to [73e9e0b595d768336f37d349b7bb0c82835da1b9] # ============================================================ --- res/forms/dialogs/connect_server.ui 970d0f720ca5aef9e50ede7162e0604fa88a10df +++ res/forms/dialogs/connect_server.ui 970d0f720ca5aef9e50ede7162e0604fa88a10df @@ -0,0 +1,162 @@ + + + ConnectServerDialog + + + + 0 + 0 + 394 + 178 + + + + + 0 + 0 + + + + + 16777215 + 178 + + + + Connect to a server + + + + + + + 0 + 0 + + + + Enter a host address and select a key for authentication + + + + + + Host + + + + + + + A hostname like 'my.host.com' or a host name with a non-standard port specification, like 'my.host.com:3456'. + + + + + + + + + + Key + + + + + + + + + + + 0 + 0 + + + + SizeableLabel { + qproperty-relativeSize: 0.85; + color: red; +} + + + + + + true + + + 5 + + + + + + + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + groupBox + validationMessage + buttonBox + + + + SizeableLabel + QLabel +
SizeableLabel.h
+
+
+ + + + buttonBox + accepted() + ConnectServerDialog + accept() + + + 222 + 328 + + + 157 + 274 + + + + + buttonBox + rejected() + ConnectServerDialog + reject() + + + 290 + 334 + + + 286 + 274 + + + + +
============================================================ --- src/view/dialogs/ConnectServerDialog.cpp a4efba6c7ac92f367fed5fea02f461d2313f2e00 +++ src/view/dialogs/ConnectServerDialog.cpp a4efba6c7ac92f367fed5fea02f461d2313f2e00 @@ -0,0 +1,104 @@ +/*************************************************************************** + * 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 "ConnectServerDialog.h" +#include "MonotoneUtil.h" + +#include + +ConnectServerDialog::ConnectServerDialog(QWidget * parent) : Dialog(parent) +{ + setupUi(this); + Dialog::init(); + + validationMessage->hide(); + + timer = new QTimer(this); + timer->setInterval(1000); + + connect( + timer, SIGNAL(timeout()), + this, SLOT(serverConnectionChanged()) + ); + + connect( + serverAddress, SIGNAL(textEdited(const QString &)), + timer, SLOT(start()) + ); + + serverAddress->setValidator(new QRegExpValidator( + QRegExp("^([\\w\\-]+(\\.[\\w\\-]+)*(:\\d+)?)$"), + this + )); + + // FIXME: anonymous connections are supported from 0.99 onwards + // by remote_stdio + //privateKeys->addItem(tr(""), QString()); + + QMap keys = + MonotoneUtil::getPrivateKeyMap(MonotoneHandle::create()); + + QMapIterator it(keys); + while (it.hasNext()) + { + it.next(); + privateKeys->addItem(it.value(), it.key()); + } + + connect( + privateKeys, SIGNAL(currentIndexChanged(int)), + this, SLOT(serverConnectionChanged()) + ); +} + +void ConnectServerDialog::serverConnectionChanged() +{ + timer->stop(); + + QString address = serverAddress->text(); + if (address.isEmpty()) + return; + + QString selectedKey = + privateKeys->itemData(privateKeys->currentIndex()).toString(); + + try + { + lastValidatedHandle.clear(); + lastValidatedHandle = MonotoneHandle::create("mtn://" + selectedKey + "@" + address); + } + catch (GuitoneException & e) + { + validationMessage->setText(e.what()); + validationMessage->show(); + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + return; + } + + validationMessage->hide(); + buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); +} + +void ConnectServerDialog::accept() +{ + if (lastValidatedHandle) + { + emit sourceSelected(lastValidatedHandle); + done(0); + } +} ============================================================ --- src/view/dialogs/ConnectServerDialog.h 8d2149ca291420b113b30a054be41bc1990c198e +++ src/view/dialogs/ConnectServerDialog.h 8d2149ca291420b113b30a054be41bc1990c198e @@ -0,0 +1,47 @@ +/*************************************************************************** + * 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 CONNECTSERVERDIALOG_H +#define CONNECTSERVERDIALOG_H + +#include "ui_connect_server.h" +#include "vocab.h" +#include "Dialog.h" + +#include + +class ConnectServerDialog : public Dialog, private Ui::ConnectServerDialog +{ + Q_OBJECT +public: + ConnectServerDialog(QWidget *); + +signals: + void sourceSelected(const MonotoneHandlePtr &); + +private slots: + void serverConnectionChanged(); + void accept(); + +private: + QTimer * timer; + MonotoneHandlePtr lastValidatedHandle; +}; + +#endif + ============================================================ --- src/view/dialogs/FileDialog.cpp 6d9fb7fb22ab2735f9bd860074ca7941a7b500de +++ src/view/dialogs/FileDialog.cpp 6d9fb7fb22ab2735f9bd860074ca7941a7b500de @@ -0,0 +1,141 @@ +/*************************************************************************** + * 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 "FileDialog.h" +#include "MonotoneUtil.h" + +#include +#include +#include +#include +#include + +FileDialog::FileDialog(QWidget * parent, Qt::WindowFlags flags, MonotoneHandle::Type type) + : QFileDialog(parent, flags), expectedType(type) +{ + setOptions(DontUseNativeDialog); + + if (expectedType == MonotoneHandle::workspace_handle) + { + setWindowTitle(tr("Open a workspace")); + setLabelText(QFileDialog::FileName, QObject::tr("Workspace path:")); + setFileMode(QFileDialog::Directory); + setOptions(options() | ShowDirsOnly); + setFilter(QDir::Drives | QDir::AllDirs | QDir::NoDotAndDotDot); + } + else if (expectedType == MonotoneHandle::database_handle) + { + setWindowTitle(tr("Open a database")); + setLabelText(QFileDialog::FileName, QObject::tr("Database file:")); + setNameFilter("*.db *.mtn"); + + QList urls = sidebarUrls(); + QStringList defaultDatabaseLocations = + MonotoneUtil::getDefaultDatabaseLocations(MonotoneHandle::create()); + foreach (const QString & location, defaultDatabaseLocations) + { + QUrl url = QUrl::fromLocalFile(location); + if (!urls.contains(url)) + urls.push_back(url); + } + setSidebarUrls(urls); + } + else + I(false); + + // FIXME: all this, of course, highly depends on the Qt 4.x layout + // of the file dialog and will probably break in any other version + QGridLayout * currentLayout = qobject_cast(layout()); + + // hide the filter selection and label + currentLayout->itemAtPosition(3, 0)->widget()->hide(); + currentLayout->itemAtPosition(3, 1)->widget()->hide(); + + // fix the button box layout and orientation + QDialogButtonBox * box = + qobject_cast(currentLayout->itemAtPosition(2,2)->widget()); + box->setOrientation(Qt::Horizontal); + box->setLayoutDirection(Qt::RightToLeft); + // remove and re-add without vertical span + int buttonPos = currentLayout->indexOf(box); + currentLayout->takeAt(buttonPos); + currentLayout->addWidget(box, 2, 2); + + // add the validation message label + validationMessage = new SizeableLabel(this); + validationMessage->setStyleSheet( + "SizeableLabel { qproperty-relativeSize: 0.85; color: red; }" + ); + currentLayout->addWidget(validationMessage, 3, 1); + validationMessage->hide(); + + // remove the ugly border of the tool buttons in the upper area + QLayout * btnLayout = currentLayout->itemAtPosition(0, 1)->layout(); + for (int i=1; i<=6; i++) + { + QToolButton * btn = qobject_cast(btnLayout->itemAt(i)->widget()); + btn->setStyleSheet("QToolButton { border: none }"); + btn->setAutoRaise(true); + } + + setLayout(currentLayout); + + connect( + this, SIGNAL(currentChanged(const QString &)), + this, SLOT(slotCurrentChanged(const QString &)) + ); +} + +void FileDialog::slotCurrentChanged(const QString & path) +{ + QGridLayout * currentLayout = qobject_cast(layout()); + QDialogButtonBox * box = + qobject_cast(currentLayout->itemAtPosition(2,2)->widget()); + + try + { + lastValidatedHandle.clear(); + lastValidatedHandle = MonotoneHandle::create(path); + + if (lastValidatedHandle->getType() != expectedType) + { + lastValidatedHandle.clear(); + throw GuitoneException("wrong or empty source picked"); + } + } + catch (GuitoneException & e) + { + validationMessage->setText(e.what()); + validationMessage->show(); + box->button(QDialogButtonBox::Open)->setEnabled(false); + return; + } + + validationMessage->hide(); + box->button(QDialogButtonBox::Open)->setEnabled(true); +} + +void FileDialog::accept() +{ + if (lastValidatedHandle) + { + emit sourceSelected(lastValidatedHandle); + done(0); + } +} + ============================================================ --- src/view/dialogs/FileDialog.h 470760cd190923eca54967c9a357a8376197ce9f +++ src/view/dialogs/FileDialog.h 470760cd190923eca54967c9a357a8376197ce9f @@ -0,0 +1,47 @@ +/*************************************************************************** + * 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 FILEDIALOG_H +#define FILEDIALOG_H + +#include "vocab.h" +#include "SizeableLabel.h" + +#include + +class FileDialog : public QFileDialog +{ + Q_OBJECT +public: + FileDialog(QWidget *, Qt::WindowFlags, MonotoneHandle::Type); + +signals: + void sourceSelected(const MonotoneHandlePtr &); + +private slots: + void slotCurrentChanged(const QString &); + void accept(); + +private: + SizeableLabel * validationMessage; + MonotoneHandle::Type expectedType; + MonotoneHandlePtr lastValidatedHandle; +}; + +#endif + ============================================================ --- sources.pri 44e57545b5c69a8a7622c007b97d13be5f5b1867 +++ sources.pri 2ab63afc8aff74062cfe2afea515d0f6e6ed2c64 @@ -57,7 +57,8 @@ 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/dialogs/FileDialog.h \ + src/view/dialogs/ConnectServerDialog.h \ src/view/panels/IconHelp.h \ src/view/panels/DatabaseVariables.h \ src/view/panels/NodeInfo.h \ @@ -162,7 +163,8 @@ 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/dialogs/FileDialog.cpp \ + src/view/dialogs/ConnectServerDialog.cpp \ src/view/panels/IconHelp.cpp \ src/view/panels/DatabaseVariables.cpp \ src/view/panels/NodeInfo.cpp \ @@ -241,7 +243,7 @@ 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/dialogs/connect_server.ui \ res/forms/panels/icon_help.ui \ res/forms/panels/db_variables.ui \ res/forms/panels/nodeinfo.ui ============================================================ --- src/view/dialogs/DialogManager.cpp 35f72fd35f216759ced9c232dfd6f618bdc255bd +++ src/view/dialogs/DialogManager.cpp d7365a29a00859e3bd859b7c0772cd1951ee8780 @@ -18,6 +18,8 @@ #include "DialogManager.h" #include "vocab.h" +#include "FileDialog.h" +#include "ConnectServerDialog.h" DialogManager::DialogManager(QWidget * parentWidget) : QObject(parentWidget), about(0), preferences(0), @@ -97,21 +99,29 @@ void DialogManager::showSourcePicker(con void DialogManager::showSourcePicker(const MonotoneHandle::Type & type) { - if (!sourcePicker) + if (sourcePicker) { - sourcePicker = new SourcePicker(parentWidget()); + delete sourcePicker; + } - connect( - sourcePicker, SIGNAL(sourceSelected(const MonotoneHandlePtr &)), - this, SIGNAL(sourceSelected(const MonotoneHandlePtr &)) - ); + if (type == MonotoneHandle::server_handle) + { + sourcePicker = new ConnectServerDialog(parentWidget()); } + else + { + sourcePicker = new FileDialog(parentWidget(), 0, type); + } - sourcePicker->init(type); + connect( + sourcePicker, SIGNAL(sourceSelected(const MonotoneHandlePtr &)), + this, SIGNAL(sourceSelected(const MonotoneHandlePtr &)) + ); + showDialog(sourcePicker); } -void DialogManager::showDialog(Dialog * dlg) +void DialogManager::showDialog(QDialog * dlg) { if (!openDialogs.contains(dlg)) { @@ -129,7 +139,7 @@ void DialogManager::dialogFinished() void DialogManager::dialogFinished() { - Dialog * dlg = qobject_cast(sender()); + QDialog * dlg = qobject_cast(sender()); I(openDialogs.contains(dlg)); disconnect( @@ -156,7 +166,7 @@ void DialogManager::dialogFinished() // dialog... while (true) { - Dialog * other = openDialogs.pop(); + QDialog * other = openDialogs.pop(); disconnect( other, SIGNAL(finished(int)), this, SLOT(dialogFinished()) @@ -169,7 +179,7 @@ void DialogManager::dialogFinished() // is there anything to raise? if (!openDialogs.isEmpty()) { - Dialog * other = openDialogs.top(); + QDialog * other = openDialogs.top(); other->raise(); other->activateWindow(); return; ============================================================ --- src/view/dialogs/DialogManager.h e9a0ddda832900391b7edd4f182d144a675d74e7 +++ src/view/dialogs/DialogManager.h 343b2372939ed1dbe4fc6de062a1041204b756de @@ -23,7 +23,6 @@ #include "Preferences.h" #include "CreateDatabase.h" #include "ChangeKeyPassword.h" -#include "SourcePicker.h" #include "vocab.h" @@ -52,18 +51,18 @@ protected: protected: QWidget * parentWidget() const; - void showDialog(Dialog *); + void showDialog(QDialog *); About * about; Preferences * preferences; CreateDatabase * createDatabase; ChangeKeyPassword * changeKeyPassword; - SourcePicker * sourcePicker; + QDialog * sourcePicker; private: void cleanup(); - QStack openDialogs; + QStack openDialogs; private slots: void dialogFinished(); ============================================================ --- src/view/dialogs/OpenPrompt.cpp 7140354d40e226daa36a809362cbebbfbf644a85 +++ src/view/dialogs/OpenPrompt.cpp feb81552935435e828076c6024187ce978321316 @@ -218,7 +218,7 @@ void OpenPrompt::updateRecentLists() QString label = server; if (rx.indexIn(label) != -1) { - label = QString("%1 (%2...)").arg(rx.cap(2)).arg(rx.cap(1).left(8)); + label = tr("%1 (%2...)").arg(rx.cap(2)).arg(rx.cap(1).left(8)); } recentServers->insertItem(++c, label, server); } ============================================================ --- src/view/mainwindows/ServerWindow.cpp 95e24fe707f9002af347269a4d0b590374a22a7e +++ src/view/mainwindows/ServerWindow.cpp b946fbbaeb71f07104d63d3a0a52c0590a3e11c6 @@ -118,25 +118,27 @@ void ServerWindow::load(const MonotoneHa QString uri = handle->getData(); QRegExp rx("^mtn://(?:(\\w*)@)?([\\w\\-]+(?:\\.[\\w\\-]+)*(?::\\d+)?)$"); - if (rx.indexIn(uri) != -1) - { - serverAddressLabel->setText(tr("Server: %1").arg(rx.cap(2))); + I(rx.indexIn(uri) >= 0); - if (rx.cap(1).isEmpty()) - { - privateKeyLabel->setText(tr("Authentication: %1").arg("")); - } - else - { - QMap map = - MonotoneUtil::getPrivateKeyMap(MonotoneHandle::create()); - I(map.contains(rx.cap(1))); - privateKeyLabel->setText(tr("Authentication: %1").arg(map.value(rx.cap(1)))); - } + QString winTitle; + serverAddressLabel->setText(tr("Server: %1").arg(rx.cap(2))); + + if (rx.cap(1).isEmpty()) + { + privateKeyLabel->setText(tr("Authentication: %1").arg("")); + winTitle = tr("%1 ()").arg(rx.cap(2)); } + else + { + QMap map = + MonotoneUtil::getPrivateKeyMap(MonotoneHandle::create()); + I(map.contains(rx.cap(1))); + privateKeyLabel->setText(tr("Authentication: %1").arg(map.value(rx.cap(1)))); + winTitle = tr("%1 (%2...)").arg(rx.cap(2)).arg(rx.cap(1).left(8)); + } setWindowTitle( - tr("%1 - server mode - guitone").arg(handle->getData()) + tr("%1 - server mode - guitone").arg(winTitle) ); reinterpret_cast(dialogManager)->init(handle); ============================================================ --- src/view/widgets/MenuBar.cpp 24674587777e567a8b9ca191db096e1cc777ddd5 +++ src/view/widgets/MenuBar.cpp 73e9e0b595d768336f37d349b7bb0c82835da1b9 @@ -233,7 +233,7 @@ void MenuBar::updateRecentLists() QString label = previousServers[i]; if (rx.indexIn(label) != -1) { - label = QString("%1 (%2...)").arg(rx.cap(2)).arg(rx.cap(1).left(8)); + label = tr("%1 (%2...)").arg(rx.cap(2)).arg(rx.cap(1).left(8)); } act = menuRecent_Servers->addAction(