# HG changeset patch # User Chris Cannam # Date 1290093279 0 # Node ID 6d5a5571caec3b8f6cf260bdb2d48ed551872a38 # Parent b918e57c7bea70020fc034de360dc985632d405c * Basic working "Open Repository" dialog diff -r b918e57c7bea -r 6d5a5571caec easyhg.pro --- a/easyhg.pro Wed Nov 17 22:13:34 2010 +0000 +++ b/easyhg.pro Thu Nov 18 15:14:39 2010 +0000 @@ -7,6 +7,9 @@ DESTDIR = . } +OBJECTS_DIR = o +MOC_DIR = o + HEADERS = mainwindow.h \ hgexpwidget.h \ common.h \ @@ -26,7 +29,8 @@ recentfiles.h \ startupdialog.h \ repositorydialog.h \ - multichoicedialog.h + multichoicedialog.h \ + selectablelabel.h SOURCES = main.cpp \ mainwindow.cpp \ hgexpwidget.cpp \ @@ -47,16 +51,17 @@ recentfiles.cpp \ startupdialog.cpp \ repositorydialog.cpp \ - multichoicedialog.cpp + multichoicedialog.cpp \ + selectablelabel.cpp macx-* { SOURCES += common_osx.mm } # ! [0] -RESOURCES = hgexplorer.qrc +RESOURCES = easyhg.qrc win32 { - RC_FILE = hgexplorer.rc + RC_FILE = easyhg.rc } QT += network opengl diff -r b918e57c7bea -r 6d5a5571caec easyhg.qrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/easyhg.qrc Thu Nov 18 15:14:39 2010 +0000 @@ -0,0 +1,26 @@ + + + images/add.png + images/commit.png + images/diff.png + images/folderdiff.png + images/exit.png + images/merge.png + images/pull.png + images/push.png + images/remove.png + images/settings.png + images/status.png + images/undo.png + images/update.png + images/incoming.png + images/chgsetdiff.png + images/browser.png + images/browser-64.png + images/hglogo.png + images/hglogo-64.png + images/hdd_unmount.png + images/hdd_unmount-64.png + images/fileopen.png + + diff -r b918e57c7bea -r 6d5a5571caec hgexplorer.qrc --- a/hgexplorer.qrc Wed Nov 17 22:13:34 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ - - - images/add.png - images/commit.png - images/diff.png - images/folderdiff.png - images/exit.png - images/merge.png - images/pull.png - images/push.png - images/remove.png - images/settings.png - images/status.png - images/undo.png - images/update.png - images/incoming.png - images/chgsetdiff.png - - diff -r b918e57c7bea -r 6d5a5571caec images/browser-64.png Binary file images/browser-64.png has changed diff -r b918e57c7bea -r 6d5a5571caec images/browser.png Binary file images/browser.png has changed diff -r b918e57c7bea -r 6d5a5571caec images/hdd_unmount-64.png Binary file images/hdd_unmount-64.png has changed diff -r b918e57c7bea -r 6d5a5571caec images/hdd_unmount.png Binary file images/hdd_unmount.png has changed diff -r b918e57c7bea -r 6d5a5571caec images/hglogo-64.png Binary file images/hglogo-64.png has changed diff -r b918e57c7bea -r 6d5a5571caec images/hglogo.png Binary file images/hglogo.png has changed diff -r b918e57c7bea -r 6d5a5571caec images/logo-droplets.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/images/logo-droplets.svg Thu Nov 18 15:14:39 2010 +0000 @@ -0,0 +1,5 @@ + + +image/svg+xmlMercurial "droplets" logoCali Mastny and Matt MackallFeb 12 2008 + + diff -r b918e57c7bea -r 6d5a5571caec mainwindow.cpp --- a/mainwindow.cpp Wed Nov 17 22:13:34 2010 +0000 +++ b/mainwindow.cpp Thu Nov 18 15:14:39 2010 +0000 @@ -31,6 +31,7 @@ #include "mainwindow.h" #include "settingsdialog.h" +#include "multichoicedialog.h" #include "startupdialog.h" #include "colourset.h" #include "debug.h" @@ -694,14 +695,59 @@ } +void MainWindow::open() +{ + MultiChoiceDialog *d = new MultiChoiceDialog + (tr("Open Repository"), + tr("What would you like to open?"), + this); + + d->addChoice("remote", + tr("

Remote repository
"), + tr("Open an existing remote repository, by cloning a Mercurial repository URL into a local folder."), + MultiChoiceDialog::UrlArg); + + d->addChoice("local", + tr("

Local repository
"), + tr("Open an existing local Mercurial repository."), + MultiChoiceDialog::DirectoryArg); + + d->addChoice("init", + tr("

File folder
"), + tr("Open a local folder, by creating a Mercurial repository in it."), + MultiChoiceDialog::DirectoryArg); + + d->setCurrentChoice("local"); + + if (d->exec() == QDialog::Accepted) { + + QString choice = d->getCurrentChoice(); + QString arg = d->getArgument().trimmed(); + + if (choice == "local") { + workFolderPath = arg; + } else { + //!!! + } + + hgExp->clearLists(); + enableDisableActions(); + hgStat(); + } + + delete d; +} + void MainWindow::settings() { +/*!!! SettingsDialog *settingsDlg = new SettingsDialog(this); settingsDlg->setModal(true); settingsDlg->exec(); hgExp -> clearLists(); enableDisableActions(); hgStat(); +*/ } #define STDOUT_NEEDS_BIG_WINDOW 512 @@ -951,9 +997,8 @@ switch(runningAction) { case ACT_STAT: - { - hgExp -> updateWorkFolderFileList(runner -> getStdOut()); - } + MultiChoiceDialog::addRecentArgument("local", workFolderPath); + hgExp -> updateWorkFolderFileList(runner -> getStdOut()); break; case ACT_INCOMING: @@ -975,11 +1020,15 @@ break; case ACT_INIT: + MultiChoiceDialog::addRecentArgument("init", workFolderPath); + MultiChoiceDialog::addRecentArgument("local", workFolderPath); enableDisableActions(); shouldHgStat = true; break; case ACT_CLONEFROMREMOTE: + MultiChoiceDialog::addRecentArgument("local", workFolderPath); + MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath); QMessageBox::information(this, "Clone", runner -> getStdOut()); enableDisableActions(); shouldHgStat = true; @@ -1108,6 +1157,7 @@ connect(hgIgnoreAct, SIGNAL(triggered()), this, SLOT(hgIgnore())); connect(settingsAct, SIGNAL(triggered()), this, SLOT(settings())); + connect(openAct, SIGNAL(triggered()), this, SLOT(open())); connect(hgInitAct, SIGNAL(triggered()), this, SLOT(hgInit())); connect(hgCloneFromRemoteAct, SIGNAL(triggered()), this, SLOT(hgCloneFromRemote())); @@ -1310,6 +1360,10 @@ hgCloneFromRemoteAct = new QAction(tr("Clone from remote"), this); hgCloneFromRemoteAct->setStatusTip(tr("Clone from remote repository into local repository in selected folder")); + openAct = new QAction(QIcon(":/images/fileopen.png"), tr("Open..."), this); + openAct -> setStatusTip(tr("Open repository")); + openAct -> setIconVisibleInMenu(true); + settingsAct = new QAction(QIcon(":/images/settings.png"), tr("Settings..."), this); settingsAct -> setStatusTip(tr("View and change application settings")); settingsAct -> setIconVisibleInMenu(true); @@ -1399,6 +1453,7 @@ fileMenu -> addAction(hgInitAct); fileMenu -> addAction(hgCloneFromRemoteAct); fileMenu -> addSeparator(); + fileMenu -> addAction(openAct); fileMenu -> addAction(settingsAct); fileMenu -> addSeparator(); fileMenu -> addAction(exitAct); @@ -1427,7 +1482,7 @@ { fileToolBar = addToolBar(tr("File")); fileToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE)); - fileToolBar -> addAction(settingsAct); + fileToolBar -> addAction(openAct); fileToolBar -> addAction(hgStatAct); fileToolBar -> addSeparator(); // fileToolBar -> addAction(hgChgSetDiffAct); @@ -1467,6 +1522,9 @@ statusBar()->showMessage(tr("Ready")); } + +//!!! review these: + void MainWindow::readSettings() { QDir workFolder; diff -r b918e57c7bea -r 6d5a5571caec mainwindow.h --- a/mainwindow.h Wed Nov 17 22:13:34 2010 +0000 +++ b/mainwindow.h Thu Nov 18 15:14:39 2010 +0000 @@ -88,6 +88,7 @@ private slots: void about(); void settings(); + void open(); void startupDialog(); void hgRemove(); @@ -147,6 +148,7 @@ //File menu actions QAction *hgInitAct; QAction *hgCloneFromRemoteAct; + QAction *openAct; QAction *settingsAct; QAction *exitAct; diff -r b918e57c7bea -r 6d5a5571caec multichoicedialog.cpp --- a/multichoicedialog.cpp Wed Nov 17 22:13:34 2010 +0000 +++ b/multichoicedialog.cpp Thu Nov 18 15:14:39 2010 +0000 @@ -17,7 +17,16 @@ #include "multichoicedialog.h" +#include "selectablelabel.h" + +#include "debug.h" + #include +#include +#include +#include +#include +#include MultiChoiceDialog::MultiChoiceDialog(QString title, QString heading, QWidget *parent) : QDialog(parent) @@ -31,26 +40,204 @@ outer->addWidget(new QLabel(heading), 0, 0, 1, 3); QWidget *innerWidget = new QWidget; - outer->addWidget(innerWidget, 1, 0, 1, 2); - m_choiceLayout = new QGridLayout; + outer->addWidget(innerWidget, 1, 0, 1, 3); + m_choiceLayout = new QHBoxLayout; innerWidget->setLayout(m_choiceLayout); m_descriptionLabel = new QLabel; outer->addWidget(m_descriptionLabel, 2, 0, 1, 3); + QFont f = m_descriptionLabel->font(); + f.setPointSize(f.pointSize() * 0.9); + m_descriptionLabel->setFont(f); + m_argLabel = new QLabel(); outer->addWidget(m_argLabel, 3, 0); - m_argEdit = new QLineEdit(); + m_argEdit = new QComboBox(); + m_argEdit->setEditable(true); outer->addWidget(m_argEdit, 3, 1); + outer->setColumnStretch(1, 20); m_browseButton = new QPushButton(tr("Browse...")); outer->addWidget(m_browseButton, 3, 2); + connect(m_browseButton, SIGNAL(clicked()), this, SLOT(browse())); QDialogButtonBox *bbox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(bbox, SIGNAL(accepted()), this, SLOT(accept())); connect(bbox, SIGNAL(rejected()), this, SLOT(reject())); outer->addWidget(bbox, 4, 0, 1, 3); + + setMinimumWidth(480); } +QString +MultiChoiceDialog::getCurrentChoice() +{ + return m_currentChoice; +} + +void +MultiChoiceDialog::setCurrentChoice(QString c) +{ + m_currentChoice = c; + choiceChanged(); +} + +QString +MultiChoiceDialog::getArgument() +{ + return m_argEdit->currentText(); +} + +void +MultiChoiceDialog::addRecentArgument(QString id, QString arg) +{ + RecentFiles(QString("Recent-%1").arg(id)).addFile(arg); +} + +void +MultiChoiceDialog::addChoice(QString id, QString text, + QString description, ArgType arg) +{ + bool first = (m_texts.empty()); + + m_texts[id] = text; + m_descriptions[id] = description; + m_argTypes[id] = arg; + + if (arg != NoArg) { + m_recentFiles[id] = QSharedPointer + (new RecentFiles(QString("Recent-%1").arg(id))); + } + + SelectableLabel *cb = new SelectableLabel; + cb->setSelectedText(text); + cb->setUnselectedText(text); + + m_choiceLayout->addWidget(cb); + m_choiceButtons[cb] = id; + + connect(cb, SIGNAL(selectionChanged()), this, SLOT(choiceChanged())); + + if (first) { + m_currentChoice = id; + choiceChanged(); + } +} + +void +MultiChoiceDialog::browse() +{ + QString origin = getArgument(); + + if (origin == "") { +#ifdef Q_OS_WIN32 + origin = "c:"; +#else + origin = QDir::homePath(); +#endif + } + + QString path = origin; + + if (m_argTypes[m_currentChoice] == DirectoryArg) { + + path = QFileDialog::getExistingDirectory + (this, tr("Open Directory"), origin, + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (path != QString()) { + m_argEdit->lineEdit()->setText(path + QDir::separator()); + } + + } else { + + path = QFileDialog::getOpenFileName + (this, tr("Open File"), origin); + if (path != QString()) { + m_argEdit->lineEdit()->setText(path); + } + } +} + +void +MultiChoiceDialog::choiceChanged() +{ + DEBUG << "choiceChanged" << endl; + + if (m_choiceButtons.empty()) return; + + QString id = ""; + + QObject *s = sender(); + QWidget *w = qobject_cast(s); + if (w) id = m_choiceButtons[w]; + + if (id == m_currentChoice) return; + if (id == "") { + // Happens when this is called for the very first time, when + // m_currentChoice has been set to the intended ID but no + // button has actually been pressed -- then we need to + // initialise + id = m_currentChoice; + } + + m_currentChoice = id; + + foreach (QWidget *cw, m_choiceButtons.keys()) { + SelectableLabel *sl = qobject_cast(cw); + if (sl) { + sl->setSelected(m_choiceButtons[cw] == id); + } + } + + m_descriptionLabel->setText(m_descriptions[id]); + + switch (m_argTypes[id]) { + + case NoArg: + m_argLabel->hide(); + m_argEdit->hide(); + m_browseButton->hide(); + break; + + case FileArg: + m_argLabel->setText(tr("File:")); + m_argLabel->show(); + m_argEdit->show(); + m_browseButton->show(); + break; + + case DirectoryArg: + m_argLabel->setText(tr("Folder:")); + m_argLabel->show(); + m_argEdit->show(); + m_browseButton->show(); + break; + + case UrlArg: + m_argLabel->setText(tr("URL:")); + m_argLabel->show(); + m_argEdit->show(); + m_browseButton->hide(); + break; + + case FileOrUrlArg: + m_argLabel->setText(tr("File or URL:")); + m_argLabel->show(); + m_argEdit->show(); + m_browseButton->show(); + break; + } + + if (m_argTypes[id] != NoArg) { + QSharedPointer rf = m_recentFiles[id]; + m_argEdit->clear(); + m_argEdit->addItems(rf->getRecent()); + } + + adjustSize(); +} + + diff -r b918e57c7bea -r 6d5a5571caec multichoicedialog.h --- a/multichoicedialog.h Wed Nov 17 22:13:34 2010 +0000 +++ b/multichoicedialog.h Thu Nov 18 15:14:39 2010 +0000 @@ -18,24 +18,31 @@ #ifndef MULTICHOICEDIALOG_H #define MULTICHOICEDIALOG_H +#include "recentfiles.h" + #include #include -#include +#include #include #include #include #include +#include #include +#include +#include class MultiChoiceDialog : public QDialog { Q_OBJECT public: - explicit MultiChoiceDialog(QString title, QString heading, QWidget *parent = 0); + explicit MultiChoiceDialog(QString title, QString heading, + QWidget *parent = 0); enum ArgType { NoArg, FileArg, + DirectoryArg, UrlArg, FileOrUrlArg }; @@ -43,29 +50,30 @@ void addChoice(QString identifier, QString text, QString description, ArgType arg); - QString getSelectedIdentifier(); + void setCurrentChoice(QString); + QString getCurrentChoice(); QString getArgument(); -signals: + static void addRecentArgument(QString identifier, QString name); private slots: - + void choiceChanged(); + void browse(); private: - void updateArgWidgets(); // when choice changes - QMap m_texts; QMap m_descriptions; + QMap m_argTypes; + QMap > m_recentFiles; QString m_currentChoice; - QMap m_choiceButtons; + QMap m_choiceButtons; - QGridLayout *m_choiceLayout; + QHBoxLayout *m_choiceLayout; QLabel *m_descriptionLabel; QLabel *m_argLabel; - QLineEdit *m_argEdit; - QPushButton *m_browseButton; - + QComboBox *m_argEdit; + QAbstractButton *m_browseButton; }; #endif // MULTICHOICEDIALOG_H diff -r b918e57c7bea -r 6d5a5571caec recentfiles.h --- a/recentfiles.h Wed Nov 17 22:13:34 2010 +0000 +++ b/recentfiles.h Thu Nov 18 15:14:39 2010 +0000 @@ -59,10 +59,9 @@ * Add a name that is known to be either a file path or a URL. If * it looks like a URL, add it literally; otherwise treat it as a * file path and canonicalise it appropriately. Also takes into - * account the user preference for whether to include temporary - * files in the recent files menu: the file will not be added if - * the preference is set and the file appears to be a temporary - * one. + * account the preference for whether to include temporary files + * in the recent files menu: the file will not be added if the + * preference is set and the file appears to be a temporary one. */ void addFile(QString name); diff -r b918e57c7bea -r 6d5a5571caec selectablelabel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/selectablelabel.cpp Thu Nov 18 15:14:39 2010 +0000 @@ -0,0 +1,151 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + EasyMercurial + + Based on HgExplorer by Jari Korhonen + Copyright (c) 2010 Jari Korhonen + Copyright (c) 2010 Chris Cannam + Copyright (c) 2010 Queen Mary, University of London + + 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 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "selectablelabel.h" + +#include "debug.h" + +#include +#include + +SelectableLabel::SelectableLabel(QWidget *p) : + QLabel(p), + m_selected(false) +{ + setTextFormat(Qt::RichText); +// setLineWidth(2); +// setFixedWidth(480); + setupStyle(); + setOpenExternalLinks(true); +} + +SelectableLabel::~SelectableLabel() +{ +} + +void +SelectableLabel::setUnselectedText(QString text) +{ + if (m_unselectedText == text) return; + m_unselectedText = text; + if (!m_selected) { + setText(m_unselectedText); + resize(sizeHint()); + } +} + +void +SelectableLabel::setSelectedText(QString text) +{ + if (m_selectedText == text) return; + m_selectedText = text; + if (m_selected) { + setText(m_selectedText); + resize(sizeHint()); + } +} + +void +SelectableLabel::setupStyle() +{ + QPalette palette = QApplication::palette(); + + setTextInteractionFlags(Qt::LinksAccessibleByKeyboard | + Qt::LinksAccessibleByMouse | + Qt::TextSelectableByMouse); + + if (m_selected) { + setStyleSheet + (QString("QLabel:hover { background: %1; color: %3; } " + "QLabel:!hover { background: %2; color: %3 } " + "QLabel { padding: 7px }") + .arg(palette.highlight().color().name()) + .arg(palette.highlight().color().name()) + .arg(palette.text().color().name())); + } else { + setStyleSheet + (QString("QLabel:hover { background: %1; color: %3; } " + "QLabel:!hover { background: %2; color: %3 } " + "QLabel { padding: 7px }") + .arg(palette.button().color().name()) + .arg(palette.light().color().name()) + .arg(palette.text().color().name())); + } +} + +void +SelectableLabel::setSelected(bool s) +{ + if (m_selected == s) return; + m_selected = s; + if (m_selected) { + setText(m_selectedText); + } else { + setText(m_unselectedText); + } + setupStyle(); + parentWidget()->resize(parentWidget()->sizeHint()); +} + +void +SelectableLabel::toggle() +{ + setSelected(!m_selected); +} + +void +SelectableLabel::mousePressEvent(QMouseEvent *e) +{ + m_swallowRelease = !m_selected; + setSelected(true); + QLabel::mousePressEvent(e); + emit selectionChanged(); +} + +void +SelectableLabel::mouseDoubleClickEvent(QMouseEvent *e) +{ + QLabel::mouseDoubleClickEvent(e); + emit doubleClicked(); +} + +void +SelectableLabel::mouseReleaseEvent(QMouseEvent *e) +{ + if (!m_swallowRelease) QLabel::mouseReleaseEvent(e); + m_swallowRelease = false; +} + +void +SelectableLabel::enterEvent(QEvent *) +{ +// std::cerr << "enterEvent" << std::endl; +// QPalette palette = QApplication::palette(); +// palette.setColor(QPalette::Window, Qt::gray); +// setStyleSheet("background: gray"); +// setPalette(palette); +} + +void +SelectableLabel::leaveEvent(QEvent *) +{ +// std::cerr << "leaveEvent" << std::endl; +// setStyleSheet("background: white"); +// QPalette palette = QApplication::palette(); +// palette.setColor(QPalette::Window, Qt::gray); +// setPalette(palette); +} diff -r b918e57c7bea -r 6d5a5571caec selectablelabel.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/selectablelabel.h Thu Nov 18 15:14:39 2010 +0000 @@ -0,0 +1,57 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + EasyMercurial + + Based on HgExplorer by Jari Korhonen + Copyright (c) 2010 Jari Korhonen + Copyright (c) 2010 Chris Cannam + Copyright (c) 2010 Queen Mary, University of London + + 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 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _SELECTABLE_LABEL_H_ +#define _SELECTABLE_LABEL_H_ + +#include + +class SelectableLabel : public QLabel +{ + Q_OBJECT + +public: + SelectableLabel(QWidget *parent = 0); + virtual ~SelectableLabel(); + + void setSelectedText(QString); + void setUnselectedText(QString); + + bool isSelected() const { return m_selected; } + +signals: + void selectionChanged(); + void doubleClicked(); + +public slots: + void setSelected(bool); + void toggle(); + +protected: + virtual void mousePressEvent(QMouseEvent *e); + virtual void mouseReleaseEvent(QMouseEvent *e); + virtual void mouseDoubleClickEvent(QMouseEvent *e); + virtual void enterEvent(QEvent *); + virtual void leaveEvent(QEvent *); + void setupStyle(); + QString m_selectedText; + QString m_unselectedText; + bool m_selected; + bool m_swallowRelease; +}; + +#endif