Index: fuel.pro
==================================================================
--- fuel.pro
+++ fuel.pro
@@ -1,91 +1,102 @@
-#-------------------------------------------------
-# Fuel
-#-------------------------------------------------
-
-QT += core gui webkit
-
-contains(QT_VERSION, ^5\\..*) {
- QT += widgets webkitwidgets
-}
-
-TARGET = Fuel
-TEMPLATE = app
-
-win32 {
- RC_FILE = rsrc/fuel.rc
- LIBS += -luser32 -lshell32 -luuid
-}
-
-macx {
- ICON = rsrc/icons/fuel.icns
-}
-
-unix:!macx {
- TARGET = fuel
- ICON = rsrc/icons/fuel.png
- PREFIX = /usr
- BINDIR = $$PREFIX/bin
- DATADIR = $$PREFIX/share
- target.path = $$BINDIR
-
- desktop.path = $$DATADIR/applications
- desktop.files += rsrc/fuel.desktop
-
- icon.path = $$DATADIR/icons/hicolor/256x256/apps
- icon.files += rsrc/icons/fuel.png
-
- INSTALLS += target desktop icon
- system(intl/convert.sh)
-}
-
-
-INCLUDEPATH += src
-
-SOURCES += src/main.cpp\
- src/MainWindow.cpp \
- src/CommitDialog.cpp \
- src/FileActionDialog.cpp \
- src/SettingsDialog.cpp \
- src/Utils.cpp \
- src/FileTableView.cpp \
- src/CloneDialog.cpp \
- src/LoggedProcess.cpp \
- src/BrowserWidget.cpp \
- src/CustomWebView.cpp \
- src/Fossil.cpp \
- src/Workspace.cpp
-
-HEADERS += src/MainWindow.h \
- src/CommitDialog.h \
- src/FileActionDialog.h \
- src/SettingsDialog.h \
- src/Utils.h \
- src/FileTableView.h \
- src/CloneDialog.h \
- src/LoggedProcess.h \
- src/BrowserWidget.h \
- src/CustomWebView.h \
- src/Fossil.h \
- src/Workspace.h
-
-FORMS += ui/MainWindow.ui \
- ui/CommitDialog.ui \
- ui/FileActionDialog.ui \
- ui/SettingsDialog.ui \
- ui/CloneDialog.ui \
- ui/BrowserWidget.ui
-
-RESOURCES += \
- rsrc/resources.qrc
-
-CODECFORTR = UTF-8
-
-TRANSLATIONS += \
- intl/en_US.ts \
- intl/el_GR.ts \
- intl/de_DE.ts \
- intl/es_ES.ts \
- intl/fr_FR.ts \
- intl/ru_RU.ts \
- intl/pt_PT.ts
-
+#-------------------------------------------------
+# Fuel
+#-------------------------------------------------
+
+QT = core gui webkit
+
+contains(QT_VERSION, ^5\\..*) {
+ QT += widgets webkitwidgets
+ QT -= quick multimediawidgets opengl printsupport qml multimedia positioning sensors
+}
+
+TARGET = Fuel
+TEMPLATE = app
+
+win32 {
+ RC_FILE = rsrc/fuel.rc
+ LIBS += -luser32 -lshell32 -luuid
+}
+
+macx {
+ ICON = rsrc/icons/fuel.icns
+}
+
+unix:!macx {
+ TARGET = fuel
+ ICON = rsrc/icons/fuel.png
+ PREFIX = /usr
+ BINDIR = $$PREFIX/bin
+ DATADIR = $$PREFIX/share
+ target.path = $$BINDIR
+
+ desktop.path = $$DATADIR/applications
+ desktop.files += rsrc/fuel.desktop
+
+ icon.path = $$DATADIR/icons/hicolor/256x256/apps
+ icon.files += rsrc/icons/fuel.png
+
+ INSTALLS += target desktop icon
+ system(intl/convert.sh)
+}
+
+
+INCLUDEPATH += src
+
+SOURCES += src/main.cpp\
+ src/MainWindow.cpp \
+ src/CommitDialog.cpp \
+ src/FileActionDialog.cpp \
+ src/SettingsDialog.cpp \
+ src/FslSettingsDialog.cpp \
+ src/CloneDialog.cpp \
+ src/RevisionDialog.cpp \
+ src/Utils.cpp \
+ src/FileTableView.cpp \
+ src/LoggedProcess.cpp \
+ src/BrowserWidget.cpp \
+ src/CustomWebView.cpp \
+ src/Fossil.cpp \
+ src/Workspace.cpp \
+ src/SearchBox.cpp \
+ src/Settings.cpp
+
+HEADERS += src/MainWindow.h \
+ src/CommitDialog.h \
+ src/FileActionDialog.h \
+ src/SettingsDialog.h \
+ src/FslSettingsDialog.h \
+ src/CloneDialog.h \
+ src/RevisionDialog.h \
+ src/Utils.h \
+ src/FileTableView.h \
+ src/LoggedProcess.h \
+ src/BrowserWidget.h \
+ src/CustomWebView.h \
+ src/Fossil.h \
+ src/Workspace.h \
+ src/SearchBox.h \
+ src/Settings.h
+
+FORMS += ui/MainWindow.ui \
+ ui/CommitDialog.ui \
+ ui/FileActionDialog.ui \
+ ui/SettingsDialog.ui \
+ ui/FslSettingsDialog.ui \
+ ui/CloneDialog.ui \
+ ui/BrowserWidget.ui \
+ ui/RevisionDialog.ui
+
+RESOURCES += \
+ rsrc/resources.qrc
+
+CODECFORTR = UTF-8
+
+TRANSLATIONS += \
+ intl/en_US.ts \
+ intl/el_GR.ts \
+ intl/de_DE.ts \
+ intl/es_ES.ts \
+ intl/fr_FR.ts \
+ intl/ru_RU.ts \
+ intl/pt_PT.ts
+
Index: rsrc/resources.qrc
==================================================================
--- rsrc/resources.qrc
+++ rsrc/resources.qrc
@@ -1,163 +1,167 @@
-
- icons/Address Book-01.png
- icons/Adobe Illustrator CS3 Document-01.png
- icons/Adobe PDF Document-01.png
- icons/Adobe Photoshop CS3 Document-01.png
- icons/Battery-01.png
- icons/Binoculars-01.png
- icons/Book-01.png
- icons/Briefcase-01.png
- icons/Button Add-01.png
- icons/Button Blank Blue-01.png
- icons/Button Blank Gray-01.png
- icons/Button Blank Green-01.png
- icons/Button Blank Red-01.png
- icons/Button Blank Yellow-01.png
- icons/Button Cancel-01.png
- icons/Button Close-01.png
- icons/Button Delete-01.png
- icons/Button Download-01.png
- icons/Button Favorite-01.png
- icons/Button Forward-01.png
- icons/Button Help-01.png
- icons/Button Info-01.png
- icons/Button Log Off-01.png
- icons/Button Next-01.png
- icons/Button Pause-01.png
- icons/Button Play-01.png
- icons/Button Previous-01.png
- icons/Button Refresh-01.png
- icons/Button Reload-01.png
- icons/Button Reminder-01.png
- icons/Button Rewind-01.png
- icons/Button Talk Balloon-01.png
- icons/Button Turn Off-01.png
- icons/Button Turn On-01.png
- icons/Button Upload-01.png
- icons/Button Warning-01.png
- icons/Calculator-01.png
- icons/Calendar Blue-01.png
- icons/Calendar Green-01.png
- icons/Calendar Red-01.png
- icons/Clipboard-01.png
- icons/Clipboard Paste-01.png
- icons/Clock-01.png
- icons/Coin-01.png
- icons/Compressed File RAR-01.png
- icons/Compressed File SIT-01.png
- icons/Compressed File Zip-01.png
- icons/Computer Monitor-01.png
- icons/Computer Network-01.png
- icons/Document-01.png
- icons/Document Attach-01.png
- icons/Document Blank-01.png
- icons/Document Chart-01.png
- icons/Document Copy-01.png
- icons/Document Flow Chart-01.png
- icons/Document Gant Chart-01.png
- icons/Document Help-01.png
- icons/Document Line Chart-01.png
- icons/Document Microsoft Excel-01.png
- icons/Document Microsoft PowerPoint-01.png
- icons/Document Microsoft Word-01.png
- icons/Document Organization Chart-01.png
- icons/Document Preview-01.png
- icons/Document-Revert-icon.png
- icons/Document Text-01.png
- icons/Edit Document-01.png
- icons/Email-01.png
- icons/Email Attachment-01.png
- icons/Email Delete-01.png
- icons/Email Download-01.png
- icons/Email Forward-01.png
- icons/Email Inbox-01.png
- icons/Email Reply-01.png
- icons/File Audio-01.png
- icons/File Audio AIFF-01.png
- icons/File Audio MP3-01.png
- icons/File Audio WAV-01.png
- icons/File Audio WMA-01.png
- icons/File Delete-01.png
- icons/File History-01.png
- icons/File New-01.png
- icons/File Open-01.png
- icons/File Video 3GP-01.png
- icons/File Video-01.png
- icons/File Video AVI-01.png
- icons/File Video MOV-01.png
- icons/File Video MPEG-01.png
- icons/File Video WMV-01.png
- icons/Folder-01.png
- icons/Folder Add-01.png
- icons/Folder Compressed-01.png
- icons/Folder Delete-01.png
- icons/Folder Explorer-01.png
- icons/Folder Generic Blue-01.png
- icons/Folder Generic Green-01.png
- icons/Folder Generic Red-01.png
- icons/Folder Generic Silver-01.png
- icons/Folder Open-01.png
- icons/Folder RAR-01.png
- icons/Games-01.png
- icons/Gear-01.png
- icons/Highlighter Blue-01.png
- icons/Highlighter Green-01.png
- icons/Highlighter Yellow-01.png
- icons/Image BMP-01.png
- icons/Image GIF-01.png
- icons/Image JPEG-01.png
- icons/Image PNG-01.png
- icons/Image TIFF-01.png
- icons/Lock Lock-01.png
- icons/Lock Unlock-01.png
- icons/My Documents-01.png
- icons/My Ebooks-01.png
- icons/My Music-01.png
- icons/My Pictures.png
- icons/My Videos-01.png
- icons/My Websites-01.png
- icons/Network Firewall-01.png
- icons/Network MAC-01.png
- icons/Network PC-01.png
- icons/Network Refresh-01.png
- icons/Pen Blue-01.png
- icons/Pen Green-01.png
- icons/Pen Red-01.png
- icons/Save-01.png
- icons/Text Edit.png
- icons/USB-01.png
- icons/User Administrator Blue-01.png
- icons/User Administrator Green-01.png
- icons/User Administrator Red-01.png
- icons/User Chat-01.png
- icons/User Clients-01.png
- icons/User Coat Blue-01.png
- icons/User Coat Green-01.png
- icons/User Coat Red-01.png
- icons/User Executive Blue-01.png
- icons/User Executive Green-01.png
- icons/User Executive Red-01.png
- icons/User Group-01.png
- icons/User Preppy Blue-01.png
- icons/User Preppy Green-01.png
- icons/User Preppy Red-01.png
- icons/Web HTML-01.png
- icons/Web XML-01.png
- icons/Window-01.png
- icons/Window Refresh-01.png
- icons/Windows-01.png
- icons/Windows Cascade-01.png
- icons/Zoom-01.png
- icons/Zoom In-01.png
- icons/Zoom Out-01.png
-
-
- intl/el_GR.qm
- intl/de_DE.qm
- intl/es_ES.qm
- intl/fr_FR.qm
- intl/ru_RU.qm
- intl/pt_PT.qm
-
+
+ icons/Address Book-01.png
+ icons/Adobe Illustrator CS3 Document-01.png
+ icons/Adobe PDF Document-01.png
+ icons/Adobe Photoshop CS3 Document-01.png
+ icons/Battery-01.png
+ icons/Binoculars-01.png
+ icons/Book-01.png
+ icons/Briefcase-01.png
+ icons/Button Add-01.png
+ icons/Button Blank Blue-01.png
+ icons/Button Blank Gray-01.png
+ icons/Button Blank Green-01.png
+ icons/Button Blank Red-01.png
+ icons/Button Blank Yellow-01.png
+ icons/Button Cancel-01.png
+ icons/Button Close-01.png
+ icons/Button Close-01.png
+ icons/Button Close-01.png
+ icons/Button Delete-01.png
+ icons/Button Download-01.png
+ icons/Button Favorite-01.png
+ icons/Button Forward-01.png
+ icons/Button Help-01.png
+ icons/Button Info-01.png
+ icons/Button Log Off-01.png
+ icons/Button Next-01.png
+ icons/Button Pause-01.png
+ icons/Button Play-01.png
+ icons/Button Previous-01.png
+ icons/Button Refresh-01.png
+ icons/Button Reload-01.png
+ icons/Button Reload-01.png
+ icons/Button Reminder-01.png
+ icons/Button Rewind-01.png
+ icons/Button Talk Balloon-01.png
+ icons/Button Turn Off-01.png
+ icons/Button Turn On-01.png
+ icons/Button Upload-01.png
+ icons/Button Warning-01.png
+ icons/Calculator-01.png
+ icons/Calendar Blue-01.png
+ icons/Calendar Green-01.png
+ icons/Calendar Red-01.png
+ icons/Clipboard-01.png
+ icons/Clipboard Paste-01.png
+ icons/Clock-01.png
+ icons/Coin-01.png
+ icons/Compressed File RAR-01.png
+ icons/Compressed File SIT-01.png
+ icons/Compressed File Zip-01.png
+ icons/Computer Monitor-01.png
+ icons/Computer Network-01.png
+ icons/Document-01.png
+ icons/Document Attach-01.png
+ icons/Document Blank-01.png
+ icons/Document Chart-01.png
+ icons/Document Copy-01.png
+ icons/Document Flow Chart-01.png
+ icons/Document Gant Chart-01.png
+ icons/Document Help-01.png
+ icons/Document Line Chart-01.png
+ icons/Document Microsoft Excel-01.png
+ icons/Document Microsoft PowerPoint-01.png
+ icons/Document Microsoft Word-01.png
+ icons/Document Organization Chart-01.png
+ icons/Document Preview-01.png
+ icons/Document-Revert-icon.png
+ icons/Document Text-01.png
+ icons/Edit Document-01.png
+ icons/Email-01.png
+ icons/Email Attachment-01.png
+ icons/Email Delete-01.png
+ icons/Email Download-01.png
+ icons/Email Forward-01.png
+ icons/Email Inbox-01.png
+ icons/Email Reply-01.png
+ icons/File Audio-01.png
+ icons/File Audio AIFF-01.png
+ icons/File Audio MP3-01.png
+ icons/File Audio WAV-01.png
+ icons/File Audio WMA-01.png
+ icons/File Delete-01.png
+ icons/File History-01.png
+ icons/File New-01.png
+ icons/File Open-01.png
+ icons/File Video 3GP-01.png
+ icons/File Video-01.png
+ icons/File Video AVI-01.png
+ icons/File Video MOV-01.png
+ icons/File Video MPEG-01.png
+ icons/File Video WMV-01.png
+ icons/Folder-01.png
+ icons/Folder Add-01.png
+ icons/Folder Compressed-01.png
+ icons/Folder Delete-01.png
+ icons/Folder Explorer-01.png
+ icons/Folder Explorer-01.png
+ icons/Folder Generic Blue-01.png
+ icons/Folder Generic Green-01.png
+ icons/Folder Generic Red-01.png
+ icons/Folder Generic Silver-01.png
+ icons/Folder Open-01.png
+ icons/Folder RAR-01.png
+ icons/Games-01.png
+ icons/Gear-01.png
+ icons/Highlighter Blue-01.png
+ icons/Highlighter Green-01.png
+ icons/Highlighter Yellow-01.png
+ icons/Image BMP-01.png
+ icons/Image GIF-01.png
+ icons/Image JPEG-01.png
+ icons/Image PNG-01.png
+ icons/Image TIFF-01.png
+ icons/Lock Lock-01.png
+ icons/Lock Unlock-01.png
+ icons/My Documents-01.png
+ icons/My Ebooks-01.png
+ icons/My Music-01.png
+ icons/My Pictures.png
+ icons/My Videos-01.png
+ icons/My Websites-01.png
+ icons/Network Firewall-01.png
+ icons/Network MAC-01.png
+ icons/Network PC-01.png
+ icons/Network Refresh-01.png
+ icons/Pen Blue-01.png
+ icons/Pen Green-01.png
+ icons/Pen Red-01.png
+ icons/Save-01.png
+ icons/Text Edit.png
+ icons/USB-01.png
+ icons/User Administrator Blue-01.png
+ icons/User Administrator Green-01.png
+ icons/User Administrator Red-01.png
+ icons/User Chat-01.png
+ icons/User Clients-01.png
+ icons/User Coat Blue-01.png
+ icons/User Coat Green-01.png
+ icons/User Coat Red-01.png
+ icons/User Executive Blue-01.png
+ icons/User Executive Green-01.png
+ icons/User Executive Red-01.png
+ icons/User Group-01.png
+ icons/User Preppy Blue-01.png
+ icons/User Preppy Green-01.png
+ icons/User Preppy Red-01.png
+ icons/Web HTML-01.png
+ icons/Web XML-01.png
+ icons/Window-01.png
+ icons/Window Refresh-01.png
+ icons/Windows-01.png
+ icons/Windows Cascade-01.png
+ icons/Zoom-01.png
+ icons/Zoom In-01.png
+ icons/Zoom Out-01.png
+
+
+ intl/el_GR.qm
+ intl/de_DE.qm
+ intl/es_ES.qm
+ intl/fr_FR.qm
+ intl/ru_RU.qm
+ intl/pt_PT.qm
+
Index: src/CommitDialog.cpp
==================================================================
--- src/CommitDialog.cpp
+++ src/CommitDialog.cpp
@@ -2,11 +2,11 @@
#include
#include
#include "ui_CommitDialog.h"
#include "MainWindow.h" // Ugly. I know.
-CommitDialog::CommitDialog(QWidget *parent, QString title, QStringList &files, const QStringList *history, bool singleLineEntry, const QString *checkBoxText, bool *checkBoxValue) :
+CommitDialog::CommitDialog(QWidget *parent, const QString &title, QStringList &files, const QStringList *history, bool stashMode) :
QDialog(parent, Qt::Sheet),
ui(new Ui::CommitDialog)
{
ui->setupUi(this);
ui->plainTextEdit->clear();
@@ -13,20 +13,17 @@
ui->listView->setModel(&itemModel);
setWindowTitle(title);
// Activate the appropriate control based on mode
- ui->plainTextEdit->setVisible(!singleLineEntry);
- ui->lineEdit->setVisible(singleLineEntry);
+ ui->plainTextEdit->setVisible(!stashMode);
+ ui->lineEdit->setVisible(stashMode);
// Activate the checkbox if we have some text
- ui->checkBox->setVisible(checkBoxText!=0);
- if(checkBoxText && checkBoxValue)
- {
- ui->checkBox->setText(*checkBoxText);
- ui->checkBox->setCheckState(*checkBoxValue ? Qt::Checked : Qt::Unchecked);
- }
+ ui->chkRevertFiles->setVisible(stashMode);
+
+ ui->widgetBranchOptions->setVisible(!stashMode);
// Activate the combo if we have history
ui->comboBox->setVisible(history!=0);
if(history)
{
@@ -75,20 +72,16 @@
{
delete ui;
}
//------------------------------------------------------------------------------
-bool CommitDialog::run(QWidget *parent, QString title, QStringList &files, QString &commitMsg, const QStringList *history, bool singleLineEntry, const QString *checkBoxText, bool *checkBoxValue)
+bool CommitDialog::runCommit(QWidget* parent, QStringList& files, QString& commitMsg, const QStringList& commitMsgHistory, QString &branchName, bool &privateBranch)
{
- CommitDialog dlg(parent, title, files, history, singleLineEntry, checkBoxText, checkBoxValue);
+ CommitDialog dlg(parent, tr("Commit Changes"), files, &commitMsgHistory, false);
int res = dlg.exec();
- if(singleLineEntry)
- commitMsg = dlg.ui->lineEdit->text();
- else
- commitMsg = dlg.ui->plainTextEdit->toPlainText();
-
+ commitMsg = dlg.ui->plainTextEdit->toPlainText();
if(res!=QDialog::Accepted)
return false;
files.clear();
@@ -98,16 +91,41 @@
if(si->checkState()!=Qt::Checked)
continue;
files.append(si->text());
}
- if(checkBoxText)
+ branchName.clear();
+ if(dlg.ui->chkNewBranch->isChecked())
+ {
+ branchName = dlg.ui->lineBranchName->text().trimmed();
+ privateBranch = dlg.ui->chkPrivateBranch->isChecked();
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool CommitDialog::runStashNew(QWidget* parent, QStringList& stashedFiles, QString& stashName, bool& revertFiles)
+{
+ CommitDialog dlg(parent, tr("Stash Changes"), stashedFiles, NULL, true);
+ int res = dlg.exec();
+
+ stashName = dlg.ui->lineEdit->text();
+
+ if(res!=QDialog::Accepted)
+ return false;
+
+ stashedFiles.clear();
+ for(int i=0; icheckBox->checkState() == Qt::Checked;
+ QStandardItem *si = dlg.itemModel.item(i);
+ if(si->checkState()!=Qt::Checked)
+ continue;
+ stashedFiles.append(si->text());
}
+ revertFiles = dlg.ui->chkRevertFiles->checkState() == Qt::Checked;
return true;
}
//------------------------------------------------------------------------------
void CommitDialog::on_comboBox_activated(int index)
@@ -140,5 +158,12 @@
++num_selected;
}
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(num_selected>0);
}
+
+//------------------------------------------------------------------------------
+void CommitDialog::on_chkNewBranch_toggled(bool checked)
+{
+ ui->chkPrivateBranch->setEnabled(checked);
+ ui->lineBranchName->setEnabled(checked);
+}
Index: src/CommitDialog.h
==================================================================
--- src/CommitDialog.h
+++ src/CommitDialog.h
@@ -3,30 +3,32 @@
#include
#include
namespace Ui {
- class CommitDialog;
+ class CommitDialog;
}
class CommitDialog : public QDialog
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit CommitDialog(QWidget *parent, QString title, QStringList &files, const QStringList *history=0, bool singleLineEntry=false, const QString *checkBoxText=0, bool *checkBoxValue=0);
- ~CommitDialog();
+ explicit CommitDialog(QWidget *parent, const QString &title, QStringList &files, const QStringList *history, bool stashMode);
+ ~CommitDialog();
- static bool run(QWidget *parent, QString title, QStringList &files, QString &commitMsg, const QStringList *history=0, bool singleLineEntry=false, const QString *checkBoxText=0, bool *checkBoxValue=0);
+ static bool runStashNew(QWidget* parent, QStringList& stashedFiles, QString& stashName, bool &revertFiles);
+ static bool runCommit(QWidget* parent, QStringList& files, QString& commitMsg, const QStringList &commitMsgHistory, QString& branchName, bool& privateBranch);
private slots:
void on_comboBox_activated(int index);
void on_listView_doubleClicked(const QModelIndex &index);
void on_listView_clicked(const QModelIndex &index);
+ void on_chkNewBranch_toggled(bool checked);
private:
- Ui::CommitDialog *ui;
+ Ui::CommitDialog *ui;
QStandardItemModel itemModel;
QStringList commitMessages;
};
#endif // COMMITDIALOG_H
Index: src/Fossil.cpp
==================================================================
--- src/Fossil.cpp
+++ src/Fossil.cpp
@@ -1,9 +1,8 @@
#include "Fossil.h"
#include
#include
-#include
#include
#include
#include
#include
#include
@@ -12,10 +11,13 @@
static const unsigned char UTF8_BOM[] = { 0xEF, 0xBB, 0xBF };
// 19: [5c46757d4b9765] on 2012-04-22 04:41:15
static const QRegExp REGEX_STASH("\\s*(\\d+):\\s+\\[(.*)\\] on (\\d+)-(\\d+)-(\\d+) (\\d+):(\\d+):(\\d+)", Qt::CaseInsensitive);
+// Listening for HTTP requests on TCP port 8081
+static const QRegExp REGEX_PORT(".*TCP port ([0-9]+)\\n", Qt::CaseSensitive);
+
///////////////////////////////////////////////////////////////////////////////
RepoStatus Fossil::getRepoStatus()
{
QStringList res;
int exit_code = EXIT_FAILURE;
@@ -48,10 +50,25 @@
{
if(key=="project-name")
projectName = value;
else if(key=="repository")
repositoryFile = value;
+ else if(key=="checkout")
+ {
+ // f2121dad5e4565f55ed9ef882484dd5934af565f 2015-04-26 17:27:39 UTC
+ QStringList tokens = value.split(' ', QString::SkipEmptyParts);
+ Q_ASSERT(tokens.length()>0);
+ currentRevision = tokens[0].trimmed();
+ }
+ else if(key=="tags")
+ {
+ currentTags.clear();
+ QStringList tokens = value.split(',', QString::SkipEmptyParts);
+ foreach(const QString &tag, tokens)
+ currentTags.append(tag);
+ currentTags.sort();
+ }
}
}
return run_ok ? REPO_OK : REPO_NOT_FOUND;
}
@@ -101,10 +118,16 @@
//------------------------------------------------------------------------------
bool Fossil::listFiles(QStringList &files)
{
return runFossil(QStringList() << "ls" << "-l", &files, RUNFLAGS_SILENT_ALL);
}
+
+//------------------------------------------------------------------------------
+bool Fossil::status(QStringList &result)
+{
+ return runFossil(QStringList() << "status", &result, RUNFLAGS_SILENT_ALL);
+}
//------------------------------------------------------------------------------
bool Fossil::pushRepository()
{
return runFossil(QStringList() << "push");
@@ -174,11 +197,11 @@
// Run the diff detached
return runFossil(QStringList() << "gdiff" << QuotePath(repoFile), 0, RUNFLAGS_DETACHED);
}
//------------------------------------------------------------------------------
-bool Fossil::commitFiles(const QStringList& fileList, const QString& comment)
+bool Fossil::commitFiles(const QStringList& fileList, const QString& comment, const QString &newBranchName, bool isPrivateBranch)
{
// Do commit
QString comment_fname;
{
QTemporaryFile temp_file;
@@ -200,10 +223,21 @@
comment_file.close();
// Generate fossil parameters.
QStringList params;
params << "commit" << "--message-file" << QuotePath(comment_fname);
+
+ // Commit to new branch
+ if(!newBranchName.isEmpty())
+ {
+ params << "--branch" << newBranchName.trimmed();
+
+ // Private branches are not synced with remotes
+ if(isPrivateBranch)
+ params << "--private";
+ }
+
params << QuotePaths(fileList);
runFossil(params);
QFile::remove(comment_fname);
return true;
@@ -284,17 +318,23 @@
result.clear();
return runFossil(params, &result);
}
//------------------------------------------------------------------------------
-bool Fossil::updateRepository(QStringList &result, bool explainOnly)
+bool Fossil::updateRepository(QStringList &result, const QString &revision, bool explainOnly)
{
QStringList params;
params << "update";
if(explainOnly)
params << "--nochange";
+
+ if(revision.isEmpty())
+ params << "--latest";
+ else
+ params << revision;
+
result.clear();
return runFossil(params, &result);
}
@@ -414,10 +454,143 @@
//------------------------------------------------------------------------------
bool Fossil::stashDiff(const QString& name)
{
return runFossil(QStringList() << "stash" << "diff" << name, 0);
}
+
+//------------------------------------------------------------------------------
+bool Fossil::tagList(QStringMap& tags)
+{
+ tags.clear();
+ QStringList tagnames;
+
+ if(!runFossil(QStringList() << "tag" << "ls", &tagnames, RUNFLAGS_SILENT_ALL))
+ return false;
+
+ QStringList info;
+ foreach(const QString &line, tagnames)
+ {
+ QString tag = line.trimmed();
+
+ if(tag.isEmpty())
+ continue;
+
+ info.clear();
+
+ if(!runFossil(QStringList() << "info" << "tag:"+tag, &info, RUNFLAGS_SILENT_ALL))
+ return false;
+
+ QStringMap props;
+ ParseProperties(props, info, ':');
+ Q_ASSERT(props.contains("uuid"));
+
+ // uuid: 0e29a46f036d2e0cc89727190ad34c2dfdc5737c 2015-04-27 15:41:45 UTC
+ QStringList uuid = props["uuid"].trimmed().split(' ');
+ Q_ASSERT(uuid.length()>0);
+
+ QString revision = uuid[0].trimmed();
+ tags.insert(tag, revision);
+ }
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool Fossil::tagNew(const QString& name, const QString& revision)
+{
+ QStringList res;
+
+ if(!runFossil(QStringList() << "tag" << "add" << name << revision, &res))
+ return false;
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool Fossil::tagDelete(const QString& name, const QString &revision)
+{
+ QStringList res;
+
+ if(!runFossil(QStringList() << "tag" << "cancel" << "tag:"+name << revision, &res))
+ return false;
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool Fossil::branchList(QStringList& branches, QStringList& activeBranches)
+{
+ branches.clear();
+ activeBranches.clear();
+ QStringList res;
+
+ if(!runFossil(QStringList() << "branch" , &res, RUNFLAGS_SILENT_ALL))
+ return false;
+
+ foreach(const QString &line, res)
+ {
+ QString name = line.trimmed();
+
+ if(name.isEmpty())
+ continue;
+
+ // Active branches start with a start
+ int active_index = name.indexOf('*');
+ bool is_active = (active_index != -1) && active_index==0;
+
+ // Strip
+ if(is_active)
+ {
+ name = name.mid(is_active+1).trimmed();
+ activeBranches.append(name);
+ }
+ else
+ branches.append(name);
+ }
+
+ branches.sort();
+ activeBranches.sort();
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool Fossil::branchNew(const QString& name, const QString& revisionBasis, bool isPrivate)
+{
+ QStringList params;
+
+ params <<"branch" << "new" << name << revisionBasis;
+
+ if(isPrivate)
+ params << "--private";
+
+ QStringList res;
+
+ if(!runFossil(params, &res))
+ return false;
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool Fossil::branchMerge(QStringList &res, const QString& revision, bool integrate, bool force, bool testOnly)
+{
+ QStringList params;
+
+ params <<"merge";
+
+ if(integrate)
+ params << "--integrate";
+
+ if(force)
+ params << "--force";
+
+ if(testOnly)
+ params << "--dry-run";
+
+ params << revision;
+
+ if(!runFossil(params, &res))
+ return false;
+ return true;
+}
//------------------------------------------------------------------------------
static QString ParseFossilQuery(QString line)
{
// Extract question
@@ -563,15 +736,41 @@
QByteArray input;
process.getLogAndClear(input);
#ifdef QT_DEBUG // Log fossil output in debug builds
- if(!input.isEmpty())
+ if(!input.isEmpty() && (runFlags & RUNFLAGS_DEBUG) )
qDebug() << "[" << ++input_index << "] '" << input.data() << "'\n";
#endif
buffer += decoder->toUnicode(input);
+#if 0 // Keep this for now to simulate bad parses
+ if(runFlags & RUNFLAGS_DEBUG)
+ {
+ static int debug=1;
+ if(debug==1)
+ {
+ buffer = " 4: [df2233aabe09ef] on 2013-02-03 02:51:33\n"
+ " History\n"
+ " 5: [df2233aabe09ef] on 2013-02-15 03:55:37\n"
+ " ";
+ debug++;
+ }
+ else if(debug==2)
+ {
+ buffer = " Diff\n"
+ " ";
+ debug++;
+ }
+ else
+ buffer="";
+ }
+#endif
+ #ifdef QT_DEBUG // breakpoint
+ //if(buffer.indexOf("SQLITE_CANTOPEN")!=-1)
+ // qDebug() << "Breakpoint\n";
+ #endif
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
if(buffer.isEmpty())
continue;
@@ -591,13 +790,16 @@
// Detect previous line
if(last_line_start>0)
{
int before_last_line_start = buffer.lastIndexOf(EOL_MARK, last_line_start-1);
- // No line before ?
+
+ // No new-line before ?
if(before_last_line_start==-1)
before_last_line_start = 0; // Use entire line
+ else
+ ++before_last_line_start; // Skip new-line
// Extract previous line
before_last_line = buffer.mid(before_last_line_start, last_line_start-before_last_line_start);
}
}
@@ -617,15 +819,22 @@
// Flush all complete lines to the log and output
QStringList log_lines = buffer.left(last_line_start).split(EOL_MARK);
for(int l=0; l0 && l==log_lines.length()-1 && buffer[buffer.length()-1] != EOL_MARK )
+ // Skip last line if we have a query. This will be handled manually further down
+ if(have_query && l==log_lines.length()-1)
continue;
QString line = log_lines[l].trimmed();
+
+ #ifdef QT_DEBUG
+ if(runFlags & RUNFLAGS_DEBUG)
+ {
+ qDebug() << "LINE: " << line << "\n";
+ }
+ #endif
if(line.isEmpty())
continue;
if(output)
@@ -791,18 +1000,68 @@
log("> fossil ui
", true);
log(QObject::tr("Starting Fossil browser UI. Please wait.")+"\n");
QString fossil = getFossilPath();
- fossilUI.start(fossil, QStringList() << "server" << "--localauth" << "-P" << httpPort );
+ QStringList params;
+ params << "server" << "--localauth";
+
+ if(!httpPort.isEmpty())
+ params << "-P" << httpPort;
+
+ fossilUI.start(getFossilPath(), params);
if(!fossilUI.waitForStarted() || fossilUI.state()!=QProcess::Running)
{
log(QObject::tr("Could not start Fossil executable '%s'").arg(fossil)+"\n");
return false;
}
+#ifdef Q_OS_WIN
+ QTextCodec *codec = QTextCodec::codecForName("UTF-8");
+#else
+ QTextCodec *codec = QTextCodec::codecForLocale();
+#endif
+
+ Q_ASSERT(codec);
+ QTextDecoder *decoder = codec->makeDecoder();
+ Q_ASSERT(decoder);
+
+ fossilUIPort.clear();
+
+ // Wait for fossil to report the http port
+ QString buffer;
+ while(true)
+ {
+ QProcess::ProcessState state = fossilUI.state();
+ qint64 bytes_avail = fossilUI.logBytesAvailable();
+
+ if(state!=QProcess::Running && bytes_avail<1)
+ break;
+
+ QByteArray input;
+ fossilUI.getLogAndClear(input);
+
+ buffer += decoder->toUnicode(input);
+
+ // Normalize line endings
+ buffer = buffer.replace("\r\n", "\n");
+ buffer = buffer.replace("\r", "\n");
+
+ int index = REGEX_PORT.indexIn(buffer);
+ if(index==-1)
+ {
+ QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ continue;
+ }
+
+ // Extract port
+ fossilUIPort = REGEX_PORT.cap(1).trimmed();
+
+ // Done parsing
+ break;
+ }
return true;
}
//------------------------------------------------------------------------------
void Fossil::stopUI()
@@ -814,6 +1073,15 @@
#else
fossilUI.terminate();
#endif
}
fossilUI.close();
+ fossilUIPort.clear();
+}
+
+//------------------------------------------------------------------------------
+QString Fossil::getUIHttpAddress() const
+{
+ if(fossilUIPort.isEmpty())
+ return QString();
+ return "http://127.0.0.1:"+fossilUIPort;
}
Index: src/Fossil.h
==================================================================
--- src/Fossil.h
+++ src/Fossil.h
@@ -1,12 +1,13 @@
#ifndef FOSSIL_H
#define FOSSIL_H
class QStringList;
#include
+#include
#include
-#include
+#include "LoggedProcess.h"
#include "Utils.h"
typedef QMap stashmap_t;
#define PATH_SEPARATOR "/"
@@ -15,11 +16,12 @@
{
RUNFLAGS_NONE = 0<<0,
RUNFLAGS_SILENT_INPUT = 1<<0,
RUNFLAGS_SILENT_OUTPUT = 1<<1,
RUNFLAGS_SILENT_ALL = RUNFLAGS_SILENT_INPUT | RUNFLAGS_SILENT_OUTPUT,
- RUNFLAGS_DETACHED = 1<<2
+ RUNFLAGS_DETACHED = 1<<2,
+ RUNFLAGS_DEBUG = 1<<3,
};
enum RepoStatus
{
REPO_OK,
@@ -81,20 +83,22 @@
bool closeRepository();
bool pushRepository();
bool pullRepository();
bool cloneRepository(const QString &repository, const QUrl &url, const QUrl &proxyUrl);
bool undoRepository(QStringList& result, bool explainOnly);
- bool updateRepository(QStringList& result, bool explainOnly);
+ bool updateRepository(QStringList& result, const QString& revision, bool explainOnly);
bool getFossilVersion(QString &version);
bool uiRunning() const;
bool startUI(const QString &httpPort);
void stopUI();
bool listFiles(QStringList &files);
+ bool status(QStringList& result);
+
bool diffFile(const QString &repoFile);
- bool commitFiles(const QStringList &fileList, const QString &comment);
+ bool commitFiles(const QStringList &fileList, const QString &comment, const QString& newBranchName, bool isPrivateBranch);
bool addFiles(const QStringList& fileList);
bool removeFiles(const QStringList& fileList, bool deleteLocal);
bool revertFiles(const QStringList& fileList);
bool renameFile(const QString& beforePath, const QString& afterPath, bool renameLocal);
bool getFossilSettings(QStringList& result);
@@ -108,10 +112,24 @@
bool stashDrop(const QString& name);
bool stashDiff(const QString& name);
void abortOperation() { operationAborted = true; }
+ bool tagList(QStringMap& tags);
+ bool tagNew(const QString& name, const QString& revision);
+ bool tagDelete(const QString& name, const QString& revision);
+
+ bool branchList(QStringList& branches, QStringList& activeBranches);
+ bool branchNew(const QString& name, const QString& revisionBasis, bool isPrivate=false);
+ bool branchMerge(QStringList& res, const QString& revision, bool integrate, bool force, bool testOnly);
+
+ const QString &getCurrentRevision() const { return currentRevision; }
+ const QStringList &getCurrentTags() const { return currentTags; }
+
+ const QString &getUIHttpPort() const { return fossilUIPort; }
+ QString getUIHttpAddress() const;
+
private:
void log(const QString &text, bool isHTML=false)
{
if(uiCallback)
uiCallback->logText(text, isHTML);
@@ -123,10 +141,13 @@
UICallback *uiCallback;
QString currentWorkspace;
QString fossilPath; // The value from the settings
QString repositoryFile;
QString projectName;
- QProcess fossilUI;
+ QString currentRevision;
+ QStringList currentTags;
+ LoggedProcess fossilUI;
+ QString fossilUIPort;
};
#endif // FOSSIL_H
ADDED src/FslSettingsDialog.cpp
Index: src/FslSettingsDialog.cpp
==================================================================
--- /dev/null
+++ src/FslSettingsDialog.cpp
@@ -0,0 +1,72 @@
+#include "FslSettingsDialog.h"
+#include "ui_FslSettingsDialog.h"
+#include "Utils.h"
+
+#include
+
+///////////////////////////////////////////////////////////////////////////////
+FslSettingsDialog::FslSettingsDialog(QWidget *parent, Settings &_settings) :
+ QDialog(parent, Qt::Sheet),
+ ui(new Ui::FslSettingsDialog),
+ settings(&_settings)
+{
+ ui->setupUi(this);
+
+ ui->lineUIPort->setText(settings->GetValue(FOSSIL_SETTING_HTTP_PORT).toString());
+
+ // Global Settings
+ ui->lineGDiffCommand->setText(settings->GetFossilValue(FOSSIL_SETTING_GDIFF_CMD).toString());
+ ui->lineGMergeCommand->setText(settings->GetFossilValue(FOSSIL_SETTING_GMERGE_CMD).toString());
+ ui->lineProxy->setText(settings->GetFossilValue(FOSSIL_SETTING_PROXY_URL).toString());
+
+ // Repository Settings
+ ui->lineRemoteURL->setText(settings->GetFossilValue(FOSSIL_SETTING_REMOTE_URL).toString());
+ ui->lineIgnore->setText(settings->GetFossilValue(FOSSIL_SETTING_IGNORE_GLOB).toString());
+ ui->lineIgnoreCRNL->setText(settings->GetFossilValue(FOSSIL_SETTING_CRNL_GLOB).toString());
+}
+
+//-----------------------------------------------------------------------------
+FslSettingsDialog::~FslSettingsDialog()
+{
+ delete ui;
+}
+
+//-----------------------------------------------------------------------------
+bool FslSettingsDialog::run(QWidget *parent, Settings &settings)
+{
+ FslSettingsDialog dlg(parent, settings);
+ return dlg.exec() == QDialog::Accepted;
+}
+
+//-----------------------------------------------------------------------------
+void FslSettingsDialog::on_buttonBox_accepted()
+{
+ settings->SetValue(FOSSIL_SETTING_HTTP_PORT, ui->lineUIPort->text());
+
+ settings->SetFossilValue(FOSSIL_SETTING_GDIFF_CMD, ui->lineGDiffCommand->text());
+ settings->SetFossilValue(FOSSIL_SETTING_GMERGE_CMD, ui->lineGMergeCommand->text());
+ settings->SetFossilValue(FOSSIL_SETTING_PROXY_URL, ui->lineProxy->text());
+
+ settings->SetFossilValue(FOSSIL_SETTING_REMOTE_URL, ui->lineRemoteURL->text());
+ settings->SetFossilValue(FOSSIL_SETTING_IGNORE_GLOB, ui->lineIgnore->text());
+ settings->SetFossilValue(FOSSIL_SETTING_CRNL_GLOB, ui->lineIgnoreCRNL->text());
+
+ settings->ApplyEnvironment();
+}
+
+//-----------------------------------------------------------------------------
+void FslSettingsDialog::on_btnSelectFossilGDiff_clicked()
+{
+ QString path = SelectExe(this, tr("Select Graphical Diff application"));
+ if(!path.isEmpty())
+ ui->lineGDiffCommand->setText(QDir::toNativeSeparators(path));
+}
+
+//-----------------------------------------------------------------------------
+void FslSettingsDialog::on_btnSelectGMerge_clicked()
+{
+ QString path = SelectExe(this, tr("Select Graphical Merge application"));
+ if(!path.isEmpty())
+ ui->lineGMergeCommand->setText(path);
+}
+
ADDED src/FslSettingsDialog.h
Index: src/FslSettingsDialog.h
==================================================================
--- /dev/null
+++ src/FslSettingsDialog.h
@@ -0,0 +1,33 @@
+#ifndef FSLSETTINGSDIALOG_H
+#define FSLSETTINGSDIALOG_H
+
+#include
+#include "Settings.h"
+
+namespace Ui {
+ class FslSettingsDialog;
+}
+
+class FslSettingsDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit FslSettingsDialog(QWidget *parent, Settings &_settings);
+ ~FslSettingsDialog();
+
+ static bool run(QWidget *parent, Settings &_settings);
+
+
+private slots:
+ void on_buttonBox_accepted();
+ void on_btnSelectFossilGDiff_clicked();
+ void on_btnSelectGMerge_clicked();
+
+private:
+
+ Ui::FslSettingsDialog *ui;
+ Settings *settings;
+};
+
+#endif // FSLSETTINGSDIALOG_H
Index: src/MainWindow.cpp
==================================================================
--- src/MainWindow.cpp
+++ src/MainWindow.cpp
@@ -4,20 +4,26 @@
#include
#include
#include
#include
#include
-#include
#include
#include
#include
+#include
#include
#include
+#include "SettingsDialog.h"
+#include "FslSettingsDialog.h"
+#include "SearchBox.h"
#include "CommitDialog.h"
#include "FileActionDialog.h"
#include "CloneDialog.h"
+#include "RevisionDialog.h"
#include "Utils.h"
+
+#define REVISION_LATEST "Latest revision"
//-----------------------------------------------------------------------------
enum
{
COLUMN_STATUS,
@@ -33,39 +39,55 @@
TAB_BROWSER
};
enum
{
- REPODIRMODEL_ROLE_PATH = Qt::UserRole+1
+ ROLE_WORKSPACE_ITEM = Qt::UserRole+1
+};
+
+struct WorkspaceItem
+{
+ enum
+ {
+ TYPE_UNKNOWN,
+ TYPE_WORKSPACE,
+ TYPE_FOLDER,
+ TYPE_STASHES,
+ TYPE_STASH,
+ TYPE_BRANCHES,
+ TYPE_BRANCH,
+ TYPE_TAGS,
+ TYPE_TAG,
+ TYPE_REMOTES,
+ TYPE_SETTINGS
+ };
+
+ WorkspaceItem()
+ : Type(TYPE_UNKNOWN)
+ {
+ }
+
+ WorkspaceItem(int type, const QString &value)
+ : Type(type), Value(value)
+ {
+ }
+
+ WorkspaceItem(const WorkspaceItem &other)
+ {
+ Type = other.Type;
+ Value = other.Value;
+ }
+
+ int Type;
+ QString Value;
+
+ operator QVariant() const
+ {
+ return QVariant::fromValue(*this);
+ }
};
-
-//-----------------------------------------------------------------------------
-typedef QMap QStringMap;
-static QStringMap MakeKeyValues(QStringList lines)
-{
- QStringMap res;
-
- foreach(QString l, lines)
- {
- l = l.trimmed();
- int index = l.indexOf(' ');
-
- QString key;
- QString value;
- if(index!=-1)
- {
- key = l.left(index).trimmed();
- value = l.mid(index).trimmed();
- }
- else
- key = l;
-
- res.insert(key, value);
- }
- return res;
-}
-
+Q_DECLARE_METATYPE(WorkspaceItem)
///////////////////////////////////////////////////////////////////////////////
MainWindow::MainWindow(Settings &_settings, QWidget *parent, QString *workspacePath) :
QMainWindow(parent),
ui(new Ui::MainWindow),
@@ -106,31 +128,53 @@
ui->fileTableView->horizontalHeader()->setSectionsMovable(true);
#endif
ui->fileTableView->horizontalHeader()->setStretchLastSection(true);
// workspaceTreeView
- ui->workspaceTreeView->setModel(&getWorkspace().getDirModel());
+ ui->workspaceTreeView->setModel(&getWorkspace().getTreeModel());
+
+ header.clear();
+ header << tr("Workspace");
+ getWorkspace().getTreeModel().setHorizontalHeaderLabels(header);
+
connect( ui->workspaceTreeView->selectionModel(),
SIGNAL( selectionChanged(const QItemSelection &, const QItemSelection &) ),
SLOT( onWorkspaceTreeViewSelectionChanged(const QItemSelection &, const QItemSelection &) ),
Qt::DirectConnection );
- ui->workspaceTreeView->addAction(ui->actionCommit);
- ui->workspaceTreeView->addAction(ui->actionOpenFolder);
- ui->workspaceTreeView->addAction(ui->actionAdd);
- ui->workspaceTreeView->addAction(ui->actionRevert);
- ui->workspaceTreeView->addAction(ui->actionDelete);
- ui->workspaceTreeView->addAction(separator);
- ui->workspaceTreeView->addAction(ui->actionRenameFolder);
- ui->workspaceTreeView->addAction(ui->actionOpenFolder);
-
- // StashView
- ui->stashTableView->setModel(&getWorkspace().getStashModel());
- ui->stashTableView->addAction(ui->actionApplyStash);
- ui->stashTableView->addAction(ui->actionDiffStash);
- ui->stashTableView->addAction(ui->actionDeleteStash);
- ui->stashTableView->horizontalHeader()->setSortIndicatorShown(false);
+ // Workspace Menus
+ menuWorkspace = new QMenu(this);
+ menuWorkspace->addAction(ui->actionCommit);
+ menuWorkspace->addAction(ui->actionOpenFolder);
+ menuWorkspace->addAction(ui->actionAdd);
+ menuWorkspace->addAction(ui->actionRevert);
+ menuWorkspace->addAction(ui->actionDelete);
+ menuWorkspace->addAction(separator);
+ menuWorkspace->addAction(ui->actionRenameFolder);
+ menuWorkspace->addAction(ui->actionOpenFolder);
+
+ // StashMenu
+ menuStashes = new QMenu(this);
+ menuStashes->addAction(ui->actionCreateStash);
+ menuStashes->addAction(separator);
+ menuStashes->addAction(ui->actionApplyStash);
+ menuStashes->addAction(ui->actionDiffStash);
+ menuStashes->addAction(ui->actionDeleteStash);
+
+ // TagsMenu
+ menuTags = new QMenu(this);
+ menuTags->addAction(ui->actionCreateTag);
+ menuTags->addAction(separator);
+ menuTags->addAction(ui->actionDeleteTag);
+ menuTags->addAction(ui->actionUpdate);
+
+ // BranchesMenu
+ menuBranches = new QMenu(this);
+ menuBranches->addAction(ui->actionCreateBranch);
+ menuBranches->addAction(separator);
+ menuBranches->addAction(ui->actionMergeBranch);
+ menuBranches->addAction(ui->actionUpdate);
// Recent Workspaces
// Locate a sequence of two separator actions in file menu
QList file_actions = ui->menuFile->actions();
QAction *recent_sep=0;
@@ -152,20 +196,30 @@
ui->menuFile->insertAction(recent_sep, recentWorkspaceActs[i]);
}
// TabWidget
ui->tabWidget->setCurrentIndex(TAB_LOG);
+
+ lblRevision = new QLabel();
+ ui->statusBar->insertPermanentWidget(0, lblRevision);
+ lblRevision->setVisible(true);
+
+ lblTags = new QLabel();
+ ui->statusBar->insertPermanentWidget(1, lblTags);
+ lblTags->setVisible(true);
+
// Construct ProgressBar
progressBar = new QProgressBar();
progressBar->setMinimum(0);
progressBar->setMaximum(0);
progressBar->setMaximumSize(170, 16);
progressBar->setAlignment(Qt::AlignCenter);
progressBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
- ui->statusBar->insertPermanentWidget(0, progressBar);
+ ui->statusBar->insertPermanentWidget(2, progressBar);
progressBar->setVisible(false);
+
#ifdef Q_OS_MACX
// Native applications on OSX don't have menu icons
foreach(QAction *a, ui->menuBar->actions())
a->setIconVisibleInMenu(false);
@@ -176,10 +230,34 @@
abortShortcut = new QShortcut(QKeySequence("Escape"), this);
abortShortcut->setContext(Qt::ApplicationShortcut);
abortShortcut->setEnabled(false);
connect(abortShortcut, SIGNAL(activated()), this, SLOT(onAbort()));
+ // Searchbox
+ // Add spacer to pad to right
+ QWidget* spacer = new QWidget();
+ spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ ui->mainToolBar->addWidget(spacer);
+
+ // Search shortcut
+ searchShortcut = new QShortcut(QKeySequence(QKeySequence::Find), this);
+ searchShortcut->setContext(Qt::ApplicationShortcut);
+ searchShortcut->setEnabled(true);
+ connect(searchShortcut, SIGNAL(activated()), this, SLOT(onSearch()));
+
+
+ // Create SearchBox
+ searchBox = new SearchBox(this);
+ searchBox->setPlaceholderText(tr("Find (%0)").arg(searchShortcut->key().toString()));
+ searchBox->setMaximumWidth(450);
+ ui->mainToolBar->addWidget(searchBox);
+
+ connect( searchBox,
+ SIGNAL( textChanged(const QString&)),
+ SLOT( onSearchBoxTextChanged(const QString&)),
+ Qt::DirectConnection );
+
viewMode = VIEWMODE_TREE;
uiCallback.init(this);
// Need to be before applySettings which sets the last workspace
fossil().Init(&uiCallback);
@@ -319,10 +397,11 @@
return false;
}
// Select the Root of the tree to update the file view
selectRootDir();
+ searchBox->clear();
return true;
}
//------------------------------------------------------------------------------
void MainWindow::on_actionOpenRepository_triggered()
@@ -477,31 +556,42 @@
//------------------------------------------------------------------------------
void MainWindow::enableActions(bool on)
{
- ui->actionCommit->setEnabled(on);
- ui->actionDiff->setEnabled(on);
- ui->actionAdd->setEnabled(on);
- ui->actionDelete->setEnabled(on);
- ui->actionPush->setEnabled(on);
- ui->actionPull->setEnabled(on);
- ui->actionRename->setEnabled(on);
- ui->actionHistory->setEnabled(on);
- ui->actionFossilUI->setEnabled(on);
- ui->actionRevert->setEnabled(on);
- ui->actionTimeline->setEnabled(on);
- ui->actionOpenFile->setEnabled(on);
- ui->actionOpenContaining->setEnabled(on);
- ui->actionUndo->setEnabled(on);
- ui->actionUpdate->setEnabled(on);
- ui->actionOpenFolder->setEnabled(on);
- ui->actionRenameFolder->setEnabled(on);
- ui->actionNewStash->setEnabled(on);
- ui->actionDeleteStash->setEnabled(on);
- ui->actionDiffStash->setEnabled(on);
- ui->actionApplyStash->setEnabled(on);
+ QAction *actions[] = {
+ ui->actionCommit,
+ ui->actionDiff,
+ ui->actionAdd,
+ ui->actionDelete,
+ ui->actionPush,
+ ui->actionPull,
+ ui->actionRename,
+ ui->actionHistory,
+ ui->actionFossilUI,
+ ui->actionRevert,
+ ui->actionTimeline,
+ ui->actionOpenFile,
+ ui->actionOpenContaining,
+ ui->actionUndo,
+ ui->actionUpdate,
+ ui->actionOpenFolder,
+ ui->actionRenameFolder,
+ ui->actionCreateStash,
+ ui->actionDeleteStash,
+ ui->actionDiffStash,
+ ui->actionApplyStash,
+ ui->actionDeleteStash,
+ ui->actionCreateTag,
+ ui->actionDeleteTag,
+ ui->actionCreateBranch,
+ ui->actionMergeBranch,
+ };
+
+ for(size_t i=0; isetEnabled(on);
+
}
//------------------------------------------------------------------------------
bool MainWindow::refresh()
{
QString title = "Fuel";
@@ -512,20 +602,20 @@
if(st==REPO_NOT_FOUND)
{
setStatus(tr("No workspace detected."));
enableActions(false);
getWorkspace().getFileModel().removeRows(0, getWorkspace().getFileModel().rowCount());
- getWorkspace().getDirModel().clear();
+ getWorkspace().getTreeModel().removeRows(0, getWorkspace().getFileModel().rowCount());
setWindowTitle(title);
return false;
}
else if(st==REPO_OLD_SCHEMA)
{
setStatus(tr("Old repository schema detected. Consider running 'fossil rebuild'"));
enableActions(false);
getWorkspace().getFileModel().removeRows(0, getWorkspace().getFileModel().rowCount());
- getWorkspace().getDirModel().clear();
+ getWorkspace().getTreeModel().removeRows(0, getWorkspace().getFileModel().rowCount());
setWindowTitle(title);
return true;
}
loadFossilSettings();
@@ -552,20 +642,32 @@
ui->actionViewUnchanged->isChecked(),
settings.GetFossilValue(FOSSIL_SETTING_IGNORE_GLOB).toString(),
uiCallback,
operationAborted
);
- updateDirView();
+ updateWorkspaceView();
updateFileView();
- updateStashView();
+
+ // Build default versions list
+ versionList.clear();
+ versionList += getWorkspace().getBranches();
+ versionList += getWorkspace().getTags().keys();
+
+ selectedTags.clear();
+ selectedBranches.clear();
setBusy(false);
setStatus("");
+ lblRevision->setText(tr("Revision: %0").arg(fossil().getCurrentRevision()));
+ lblRevision->setVisible(true);
+
+ lblTags->setText(tr("Tags: %0").arg(fossil().getCurrentTags().join(' ')));
+ lblTags->setVisible(true);
}
//------------------------------------------------------------------------------
-static void addPathToTree(QStandardItem &root, const QString &path)
+static void addPathToTree(QStandardItem &root, const QString &path, const QIcon &folderIcon)
{
QStringList dirs = path.split('/');
QStandardItem *parent = &root;
QString fullpath;
@@ -587,44 +689,156 @@
}
}
if(!found) // Generate it
{
- QStandardItem *child = new QStandardItem(QIcon(":icons/icons/Folder-01.png"), dir);
- child->setData(fullpath); // keep the full path to simplify selection
+ QStandardItem *child = new QStandardItem(folderIcon, dir);
+ child->setData(WorkspaceItem(WorkspaceItem::TYPE_FOLDER, fullpath), ROLE_WORKSPACE_ITEM);
parent->appendRow(child);
parent = child;
}
fullpath += '/';
}
}
//------------------------------------------------------------------------------
-void MainWindow::updateDirView()
-{
- // Directory View
- getWorkspace().getDirModel().clear();
-
- QStringList header;
- header << tr("Folders");
- getWorkspace().getDirModel().setHorizontalHeaderLabels(header);
-
- QStandardItem *root = new QStandardItem(QIcon(":icons/icons/My Documents-01.png"), fossil().getProjectName());
- root->setData(""); // Empty Path
- root->setEditable(false);
-
- getWorkspace().getDirModel().appendRow(root);
- for(stringset_t::iterator it = getWorkspace().getPaths().begin(); it!=getWorkspace().getPaths().end(); ++it)
- {
- const QString &dir = *it;
- if(dir.isEmpty())
- continue;
-
- addPathToTree(*root, dir);
- }
- ui->workspaceTreeView->expandToDepth(0);
- ui->workspaceTreeView->sortByColumn(0, Qt::AscendingOrder);
+void MainWindow::updateWorkspaceView()
+{
+ // Record expanded tree-node names, and selection
+ name_modelindex_map_t name_map;
+ BuildNameToModelIndex(name_map, getWorkspace().getTreeModel());
+ stringset_t expanded_items;
+ stringset_t selected_items;
+
+ const QItemSelection selection = ui->workspaceTreeView->selectionModel()->selection();
+
+ for(name_modelindex_map_t::const_iterator it=name_map.begin(); it!=name_map.end(); ++it)
+ {
+ const QModelIndex mi = it.value();
+ if(ui->workspaceTreeView->isExpanded(mi))
+ expanded_items.insert(it.key());
+
+ if(selection.contains(mi))
+ selected_items.insert(it.key());
+ }
+
+ // Clear content except headers
+ getWorkspace().getTreeModel().removeRows(0, getWorkspace().getTreeModel().rowCount());
+
+ QStandardItem *workspace = new QStandardItem(getInternalIcon(":icons/icon-item-folder"), tr("Files") );
+ workspace->setData(WorkspaceItem(WorkspaceItem::TYPE_WORKSPACE, ""), ROLE_WORKSPACE_ITEM);
+ workspace->setEditable(false);
+
+ getWorkspace().getTreeModel().appendRow(workspace);
+ if(viewMode == VIEWMODE_TREE)
+ {
+ for(stringset_t::iterator it = getWorkspace().getPaths().begin(); it!=getWorkspace().getPaths().end(); ++it)
+ {
+ const QString &dir = *it;
+ if(dir.isEmpty())
+ continue;
+
+ addPathToTree(*workspace, dir, getInternalIcon(":icons/icon-item-folder"));
+ }
+
+ // Expand root folder
+ ui->workspaceTreeView->setExpanded(workspace->index(), true);
+ }
+
+ // Branches
+ QStandardItem *branches = new QStandardItem(getInternalIcon(":icons/icon-item-branch"), tr("Branches"));
+ branches->setData(WorkspaceItem(WorkspaceItem::TYPE_BRANCHES, ""), ROLE_WORKSPACE_ITEM);
+ branches->setEditable(false);
+ getWorkspace().getTreeModel().appendRow(branches);
+ foreach(const QString &branch_name, getWorkspace().getBranches())
+ {
+ QStandardItem *branch = new QStandardItem(getInternalIcon(":icons/icon-item-branch"), branch_name);
+ branch->setData(WorkspaceItem(WorkspaceItem::TYPE_BRANCH, branch_name), ROLE_WORKSPACE_ITEM);
+
+ bool active = fossil().getCurrentTags().contains(branch_name);
+ if(active)
+ {
+ QFont font = branch->font();
+ font.setBold(true);
+ branch->setFont(font);
+ }
+ branches->appendRow(branch);
+ }
+
+ // Tags
+ QStandardItem *tags = new QStandardItem(getInternalIcon(":icons/icon-item-tag"), tr("Tags"));
+ tags->setData(WorkspaceItem(WorkspaceItem::TYPE_TAGS, ""), ROLE_WORKSPACE_ITEM);
+ tags->setEditable(false);
+ getWorkspace().getTreeModel().appendRow(tags);
+ for(QStringMap::const_iterator it=getWorkspace().getTags().begin(); it!=getWorkspace().getTags().end(); ++it)
+ {
+ const QString &tag_name = it.key();
+
+
+ QStandardItem *tag = new QStandardItem(getInternalIcon(":icons/icon-item-tag"), tag_name);
+ tag->setData(WorkspaceItem(WorkspaceItem::TYPE_TAG, tag_name), ROLE_WORKSPACE_ITEM);
+
+ bool active = fossil().getCurrentTags().contains(tag_name);
+ if(active)
+ {
+ QFont font = tag->font();
+ font.setBold(true);
+ tag->setFont(font);
+ }
+ tags->appendRow(tag);
+ }
+
+ // FIXME: Unique Icon name
+ // Stashes
+ QStandardItem *stashes = new QStandardItem(getInternalIcon(":icons/icon-action-repo-open"), tr("Stashes"));
+ stashes->setData(WorkspaceItem(WorkspaceItem::TYPE_STASHES, ""), ROLE_WORKSPACE_ITEM);
+ stashes->setEditable(false);
+ getWorkspace().getTreeModel().appendRow(stashes);
+ for(stashmap_t::const_iterator it= getWorkspace().getStashes().begin(); it!=getWorkspace().getStashes().end(); ++it)
+ {
+ QStandardItem *stash = new QStandardItem(getInternalIcon(":icons/icon-action-repo-open"), it.key());
+ stash->setData(WorkspaceItem(WorkspaceItem::TYPE_STASH, it.value()), ROLE_WORKSPACE_ITEM);
+ stashes->appendRow(stash);
+ }
+
+#if 0
+ // Remotes
+ QStandardItem *remotes = new QStandardItem(getInternalIcon(":icons/icon-item-remote"), tr("Remotes"));
+ remotes->setData(WorkspaceItem(WorkspaceItem::TYPE_REMOTES, ""), ROLE_WORKSPACE_ITEM);
+ remotes->setEditable(false);
+ getWorkspace().getTreeModel().appendRow(remotes);
+#endif
+
+#if 0 // Unimplemented for now
+ // Settings
+ QStandardItem *settings = new QStandardItem(getInternalIcon(":icons/icon-action-settings"), tr("Settings"));
+ settings->setData(WorkspaceItem(WorkspaceItem::TYPE_SETTINGS, ""), ROLE_WORKSPACE_ITEM);
+ settings->setEditable(false);
+ getWorkspace().getTreeModel().appendRow(settings);
+#endif
+
+ // Expand previously selected nodes
+ name_map.clear();
+ BuildNameToModelIndex(name_map, getWorkspace().getTreeModel());
+
+ for(stringset_t::const_iterator it=expanded_items.begin(); it!=expanded_items.end(); ++it)
+ {
+ name_modelindex_map_t::const_iterator mi_it = name_map.find(*it);
+ if(mi_it!=name_map.end())
+ ui->workspaceTreeView->setExpanded(mi_it.value(), true);
+ }
+
+ // Select previous selected item
+ for(stringset_t::const_iterator it=selected_items.begin(); it!=selected_items.end(); ++it)
+ {
+ name_modelindex_map_t::const_iterator mi_it = name_map.find(*it);
+ if(mi_it!=name_map.end())
+ {
+ const QModelIndex &mi = mi_it.value();
+ ui->workspaceTreeView->selectionModel()->select(mi, QItemSelectionModel::Select);
+ }
+ }
}
//------------------------------------------------------------------------------
void MainWindow::updateFileView()
{
@@ -632,65 +846,78 @@
getWorkspace().getFileModel().removeRows(0, getWorkspace().getFileModel().rowCount());
struct { WorkspaceFile::Type type; QString text; const char *icon; }
stats[] =
{
- { WorkspaceFile::TYPE_EDITTED, tr("Edited"), ":icons/icons/Button Blank Yellow-01.png" },
- { WorkspaceFile::TYPE_UNCHANGED, tr("Unchanged"), ":icons/icons/Button Blank Green-01.png" },
- { WorkspaceFile::TYPE_ADDED, tr("Added"), ":icons/icons/Button Add-01.png" },
- { WorkspaceFile::TYPE_DELETED, tr("Deleted"), ":icons/icons/Button Close-01.png" },
- { WorkspaceFile::TYPE_RENAMED, tr("Renamed"), ":icons/icons/Button Reload-01.png" },
- { WorkspaceFile::TYPE_MISSING, tr("Missing"), ":icons/icons/Button Help-01.png" },
- { WorkspaceFile::TYPE_CONFLICTED, tr("Conflicted"), ":icons/icons/Button Blank Red-01.png" },
+ { WorkspaceFile::TYPE_EDITTED, tr("Edited"), ":icons/icon-item-edited" },
+ { WorkspaceFile::TYPE_UNCHANGED, tr("Unchanged"), ":icons/icon-item-unchanged" },
+ { WorkspaceFile::TYPE_ADDED, tr("Added"), ":icons/icon-item-added" },
+ { WorkspaceFile::TYPE_DELETED, tr("Deleted"), ":icons/icon-item-deleted" },
+ { WorkspaceFile::TYPE_RENAMED, tr("Renamed"), ":icons/icon-item-renamed" },
+ { WorkspaceFile::TYPE_MISSING, tr("Missing"), ":icons/icon-item-missing" },
+ { WorkspaceFile::TYPE_CONFLICTED, tr("Conflicted"), ":icons/icon-item-conflicted" },
+ { WorkspaceFile::TYPE_MERGED, tr("Merged"), ":icons/icon-item-edited" },
};
- QFileIconProvider icon_provider;
-
bool display_path = viewMode==VIEWMODE_LIST || selectedDirs.count() > 1;
+
+ const QString &status_unknown = QString(tr("Unknown"));
+ const QString &search_text = searchBox->text();
size_t item_id=0;
for(Workspace::filemap_t::iterator it = getWorkspace().getFiles().begin(); it!=getWorkspace().getFiles().end(); ++it)
{
const WorkspaceFile &e = *it.value();
- QString path = e.getPath();
+ const QString &path = e.getPath();
+ const QString &file_path = e.getFilePath();
+ QString native_file_path = QDir::toNativeSeparators(file_path);
+
+ // Apply filter if available
+ if(!search_text.isEmpty() && !native_file_path.contains(search_text, Qt::CaseInsensitive))
+ continue;
// In Tree mode, filter all items not included in the current dir
if(viewMode==VIEWMODE_TREE && !selectedDirs.contains(path))
continue;
// Status Column
- QString status_text = QString(tr("Unknown"));
- const char *status_icon_path= ":icons/icons/Button Blank Gray-01.png"; // Default icon
+ const QString *status_text = &status_unknown;
+ const char *status_icon_path= ":icons/icon-item-unknown"; // Default icon
for(size_t t=0; tsetToolTip(status_text);
+ QStandardItem *status = new QStandardItem(getInternalIcon(status_icon_path), *status_text);
+ status->setToolTip(*status_text);
getWorkspace().getFileModel().setItem(item_id, COLUMN_STATUS, status);
QFileInfo finfo = e.getFileInfo();
- QIcon icon = icon_provider.icon(finfo);
+ QString icon_type = iconProvider.type(finfo);
+
+ if(!iconCache.contains(icon_type))
+ iconCache.insert(icon_type, iconProvider.icon(finfo));
+
+ const QIcon *icon = &iconCache[icon_type];
QStandardItem *filename_item = 0;
getWorkspace().getFileModel().setItem(item_id, COLUMN_PATH, new QStandardItem(path));
if(display_path)
- filename_item = new QStandardItem(icon, QDir::toNativeSeparators(e.getFilePath()));
+ filename_item = new QStandardItem(*icon, native_file_path);
else
- filename_item = new QStandardItem(icon, e.getFilename());
+ filename_item = new QStandardItem(*icon, e.getFilename());
Q_ASSERT(filename_item);
// Keep the path in the user data
- filename_item->setData(e.getFilePath());
+ filename_item->setData(file_path);
getWorkspace().getFileModel().setItem(item_id, COLUMN_FILENAME, filename_item);
getWorkspace().getFileModel().setItem(item_id, COLUMN_EXTENSION, new QStandardItem(finfo.suffix()));
getWorkspace().getFileModel().setItem(item_id, COLUMN_MODIFIED, new QStandardItem(finfo.lastModified().toString(Qt::SystemLocaleShortDate)));
@@ -698,29 +925,10 @@
}
ui->fileTableView->resizeRowsToContents();
}
-//------------------------------------------------------------------------------
-void MainWindow::updateStashView()
-{
- getWorkspace().getStashModel().clear();
-
- QStringList header;
- header << tr("Stashes");
- getWorkspace().getStashModel().setHorizontalHeaderLabels(header);
-
- for(stashmap_t::iterator it=getWorkspace().getStashes().begin(); it!=getWorkspace().getStashes().end(); ++it)
- {
- QStandardItem *item = new QStandardItem(it.key());
- item->setToolTip(it.key());
- getWorkspace().getStashModel().appendRow(item);
- }
- ui->stashTableView->resizeColumnsToContents();
- ui->stashTableView->resizeRowsToContents();
-}
-
//------------------------------------------------------------------------------
void MainWindow::log(const QString &text, bool isHTML)
{
QTextCursor c = ui->textBrowser->textCursor();
c.movePosition(QTextCursor::End);
@@ -812,18 +1020,14 @@
if(store->contains("ViewIgnored"))
ui->actionViewIgnored->setChecked(store->value("ViewIgnored").toBool());
if(store->contains("ViewAsList"))
{
ui->actionViewAsList->setChecked(store->value("ViewAsList").toBool());
+ ui->actionViewAsFolders->setChecked(!store->value("ViewAsList").toBool());
viewMode = store->value("ViewAsList").toBool()? VIEWMODE_LIST : VIEWMODE_TREE;
}
- ui->workspaceTreeView->setVisible(viewMode == VIEWMODE_TREE);
-
- if(store->contains("ViewStash"))
- ui->actionViewStash->setChecked(store->value("ViewStash").toBool());
- ui->stashTableView->setVisible(ui->actionViewStash->isChecked());
-
+ //ui->workspaceTreeView->setVisible(viewMode == VIEWMODE_TREE);
}
//------------------------------------------------------------------------------
void MainWindow::updateSettings()
{
@@ -858,16 +1062,16 @@
store->setValue("ViewUnknown", ui->actionViewUnknown->isChecked());
store->setValue("ViewModified", ui->actionViewModified->isChecked());
store->setValue("ViewUnchanged", ui->actionViewUnchanged->isChecked());
store->setValue("ViewIgnored", ui->actionViewIgnored->isChecked());
store->setValue("ViewAsList", ui->actionViewAsList->isChecked());
- store->setValue("ViewStash", ui->actionViewStash->isChecked());
}
//------------------------------------------------------------------------------
void MainWindow::selectRootDir()
{
+ // FIXME: KKK
if(viewMode==VIEWMODE_TREE)
{
QModelIndex root_index = ui->workspaceTreeView->model()->index(0, 0);
ui->workspaceTreeView->selectionModel()->select(root_index, QItemSelectionModel::Select);
}
@@ -879,11 +1083,11 @@
if(!uiRunning())
ui->actionFossilUI->activate(QAction::Trigger);
bool use_internal = settings.GetValue(FUEL_SETTING_WEB_BROWSER).toInt() == 1;
- QUrl url = QUrl(getFossilHttpAddress()+fossilUrl);
+ QUrl url = QUrl(fossil().getUIHttpAddress()+fossilUrl);
if(use_internal)
{
ui->webView->load(url);
ui->tabWidget->setCurrentIndex(TAB_BROWSER);
@@ -903,15 +1107,20 @@
//------------------------------------------------------------------------------
void MainWindow::getSelectionPaths(stringset_t &paths)
{
// Determine the directories selected
QModelIndexList selection = ui->workspaceTreeView->selectionModel()->selectedIndexes();
- for(QModelIndexList::iterator mi_it = selection.begin(); mi_it!=selection.end(); ++mi_it)
+ foreach(const QModelIndex &mi, selection)
{
- const QModelIndex &mi = *mi_it;
- QVariant data = getWorkspace().getDirModel().data(mi, REPODIRMODEL_ROLE_PATH);
- paths.insert(data.toString());
+ QVariant data = mi.model()->data(mi, ROLE_WORKSPACE_ITEM);
+ Q_ASSERT(data.isValid());
+
+ WorkspaceItem tv = data.value();
+ if(tv.Type != WorkspaceItem::TYPE_FOLDER)
+ continue;
+
+ paths.insert(tv.Value);
}
}
//------------------------------------------------------------------------------
// Select all workspace files that match the includeMask
void MainWindow::getAllFilenames(QStringList &filenames, int includeMask)
@@ -1006,29 +1215,27 @@
filenames.append(filename);
}
}
//------------------------------------------------------------------------------
-void MainWindow::getStashViewSelection(QStringList &stashNames, bool allIfEmpty)
-{
- QModelIndexList selection = ui->stashTableView->selectionModel()->selectedIndexes();
- if(selection.empty() && allIfEmpty)
- {
- ui->stashTableView->selectAll();
- selection = ui->stashTableView->selectionModel()->selectedIndexes();
- ui->stashTableView->clearSelection();
- }
-
- for(QModelIndexList::iterator mi_it = selection.begin(); mi_it!=selection.end(); ++mi_it)
- {
- const QModelIndex &mi = *mi_it;
-
- if(mi.column()!=0)
+void MainWindow::getSelectionStashes(QStringList &stashNames)
+{
+ QModelIndexList selection = ui->workspaceTreeView->selectionModel()->selectedIndexes();
+
+ foreach(const QModelIndex &mi, selection)
+ {
+ QVariant data = mi.model()->data(mi, ROLE_WORKSPACE_ITEM);
+ Q_ASSERT(data.isValid());
+ WorkspaceItem tv = data.value();
+
+ if(tv.Type != WorkspaceItem::TYPE_STASH)
continue;
- QString name = getWorkspace().getStashModel().data(mi).toString();
+
+ QString name = mi.model()->data(mi, Qt::DisplayRole).toString();
stashNames.append(name);
}
+
}
//------------------------------------------------------------------------------
bool MainWindow::diffFile(const QString &repoFile)
{
@@ -1047,12 +1254,11 @@
}
//------------------------------------------------------------------------------
bool MainWindow::startUI()
{
- QString port = settings.GetValue(FUEL_SETTING_HTTP_PORT).toString();
- bool started = fossil().startUI(port);
+ bool started = fossil().startUI("");
ui->actionFossilUI->setChecked(started);
return started;
}
//------------------------------------------------------------------------------
void MainWindow::stopUI()
@@ -1158,17 +1364,19 @@
void MainWindow::on_actionCommit_triggered()
{
QStringList commit_files;
getSelectionFilenames(commit_files, WorkspaceFile::TYPE_MODIFIED, true);
- if(commit_files.empty())
+ if(commit_files.empty() && !getWorkspace().otherChanges())
return;
QStringList commit_msgs = settings.GetValue(FUEL_SETTING_COMMIT_MSG).toStringList();
QString msg;
- bool aborted = !CommitDialog::run(this, tr("Commit Changes"), commit_files, msg, &commit_msgs);
+ QString branch_name="";
+ bool private_branch = false;
+ bool aborted = !CommitDialog::runCommit(this, commit_files, msg, commit_msgs, branch_name, private_branch);
// Aborted or not we always keep the commit messages.
// (This has saved me way too many times on TortoiseSVN)
if(commit_msgs.indexOf(msg)==-1)
{
@@ -1178,11 +1386,11 @@
if(aborted)
return;
// Since via the commit dialog the user can deselect all files
- if(commit_files.empty())
+ if(commit_files.empty() && !getWorkspace().otherChanges())
return;
// Do commit
QStringList files;
@@ -1194,11 +1402,11 @@
getAllFilenames(all_modified_files, WorkspaceFile::TYPE_MODIFIED);
if(commit_files.size() != all_modified_files.size())
files = commit_files;
- fossil().commitFiles(files, msg);
+ fossil().commitFiles(files, msg, branch_name, private_branch);
refresh();
}
//------------------------------------------------------------------------------
void MainWindow::on_actionAdd_triggered()
@@ -1257,11 +1465,11 @@
//------------------------------------------------------------------------------
void MainWindow::on_actionRevert_triggered()
{
QStringList modified_files;
- getSelectionFilenames(modified_files, WorkspaceFile::TYPE_EDITTED|WorkspaceFile::TYPE_ADDED|WorkspaceFile::TYPE_DELETED|WorkspaceFile::TYPE_MISSING|WorkspaceFile::TYPE_CONFLICTED);
+ getSelectionFilenames(modified_files, WorkspaceFile::TYPE_MODIFIED);
if(modified_files.empty())
return;
if(!FileActionDialog::run(this, tr("Revert files"), tr("The following files will be reverted.")+"\n"+tr("Are you sure?"), modified_files))
@@ -1372,28 +1580,17 @@
}
//------------------------------------------------------------------------------
void MainWindow::on_actionUpdate_triggered()
{
- QStringList res;
-
- // Do test update
- if(!fossil().updateRepository(res, true))
- return;
-
- // Fixme: parse "changes: None. Already up-to-date" and avoid dialog
-
- if(res.length()==0)
- return;
-
- if(!FileActionDialog::run(this, tr("Update"), tr("The following files will be updated.")+"\n"+tr("Are you sure?"), res))
- return;
-
- // Do update
- fossil().updateRepository(res, false);
-
- refresh();
+ QStringList selected = selectedBranches + selectedTags;
+
+ QString revision;
+ if(!selected.isEmpty())
+ revision = selected.first();
+
+ updateRevision(revision);
}
//------------------------------------------------------------------------------
void MainWindow::loadFossilSettings()
{
@@ -1401,11 +1598,12 @@
QStringList out;
if(!fossil().getFossilSettings(out))
return;
- QStringMap kv = MakeKeyValues(out);
+ QStringMap kv;
+ ParseProperties(kv, out);
for(Settings::mappings_t::iterator it=settings.GetMappings().begin(); it!=settings.GetMappings().end(); ++it)
{
const QString &name = it.key();
Settings::Setting::SettingType type = it->Type;
@@ -1444,14 +1642,22 @@
}
//------------------------------------------------------------------------------
void MainWindow::on_actionSettings_triggered()
{
+ // Run the dialog
+ if(!SettingsDialog::run(this, settings))
+ return;
+}
+
+//------------------------------------------------------------------------------
+void MainWindow::on_actionFossilSettings_triggered()
+{
loadFossilSettings();
// Run the dialog
- if(!SettingsDialog::run(this, settings))
+ if(!FslSettingsDialog::run(this, settings))
return;
// Apply settings
for(Settings::mappings_t::iterator it=settings.GetMappings().begin(); it!=settings.GetMappings().end(); ++it)
{
@@ -1470,10 +1676,11 @@
Q_ASSERT(type == Settings::Setting::TYPE_FOSSIL_GLOBAL || type == Settings::Setting::TYPE_FOSSIL_LOCAL);
QString value = it.value().Value.toString();
fossil().setFossilSetting(name, value, type == Settings::Setting::TYPE_FOSSIL_GLOBAL);
}
+
}
//------------------------------------------------------------------------------
void MainWindow::on_actionViewModified_triggered()
{
@@ -1495,46 +1702,73 @@
//------------------------------------------------------------------------------
void MainWindow::on_actionViewIgnored_triggered()
{
refresh();
}
+
+//------------------------------------------------------------------------------
+void MainWindow::on_actionViewAll_triggered()
+{
+ ui->actionViewModified->setChecked(true);
+ ui->actionViewUnchanged->setChecked(true);
+ ui->actionViewUnknown->setChecked(true);
+ ui->actionViewIgnored->setChecked(true);
+ refresh();
+}
//------------------------------------------------------------------------------
void MainWindow::on_actionViewAsList_triggered()
{
- viewMode = ui->actionViewAsList->isChecked() ? VIEWMODE_LIST : VIEWMODE_TREE;
- ui->workspaceTreeView->setVisible(viewMode == VIEWMODE_TREE);
+ ui->actionViewAsFolders->setChecked(!ui->actionViewAsList->isChecked());
+ viewMode = ui->actionViewAsList->isChecked() ? VIEWMODE_LIST : VIEWMODE_TREE;
+
+ updateWorkspaceView();
updateFileView();
}
//------------------------------------------------------------------------------
-QString MainWindow::getFossilHttpAddress()
+void MainWindow::on_actionViewAsFolders_triggered()
{
- QString port = settings.GetValue(FUEL_SETTING_HTTP_PORT).toString();
- return "http://127.0.0.1:"+port;
+ ui->actionViewAsList->setChecked(!ui->actionViewAsFolders->isChecked());
+ viewMode = ui->actionViewAsList->isChecked() ? VIEWMODE_LIST : VIEWMODE_TREE;
+ updateWorkspaceView();
+ updateFileView();
}
//------------------------------------------------------------------------------
void MainWindow::onWorkspaceTreeViewSelectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/)
{
- QModelIndexList selection = ui->workspaceTreeView->selectionModel()->selectedIndexes();
- int num_selected = selection.count();
+ QModelIndexList indices = ui->workspaceTreeView->selectionModel()->selectedIndexes();
// Do not modify the selection if nothing is selected
- if(num_selected==0)
+ if(indices.empty())
return;
- selectedDirs.clear();
+ stringset_t new_dirs;
+ selectedTags.clear();
+ selectedBranches.clear();
- for(int i=0; idata(id, ROLE_WORKSPACE_ITEM);
+ Q_ASSERT(data.isValid());
+ WorkspaceItem tv = data.value();
+
+ if(tv.Type == WorkspaceItem::TYPE_FOLDER || tv.Type == WorkspaceItem::TYPE_WORKSPACE)
+ new_dirs.insert(tv.Value);
+ else if(tv.Type == WorkspaceItem::TYPE_TAG)
+ selectedTags.append(tv.Value);
+ else if(tv.Type == WorkspaceItem::TYPE_BRANCH)
+ selectedBranches.append(tv.Value);
}
- updateFileView();
+ // Update the selection if we have any new folders
+ if(!new_dirs.empty() && viewMode == VIEWMODE_TREE)
+ {
+ selectedDirs = new_dirs;
+ updateFileView();
+ }
}
//------------------------------------------------------------------------------
void MainWindow::on_actionOpenFolder_triggered()
{
@@ -1548,12 +1782,18 @@
}
//------------------------------------------------------------------------------
void MainWindow::on_workspaceTreeView_doubleClicked(const QModelIndex &index)
{
- QString target = getWorkspace().getDirModel().data(index, REPODIRMODEL_ROLE_PATH).toString();
- target = getCurrentWorkspace() + PATH_SEPARATOR + target;
+ QVariant data = index.model()->data(index, ROLE_WORKSPACE_ITEM);
+ Q_ASSERT(data.isValid());
+ WorkspaceItem tv = data.value();
+
+ if(tv.Type!=WorkspaceItem::TYPE_FOLDER && tv.Type!=WorkspaceItem::TYPE_WORKSPACE)
+ return;
+
+ QString target = getCurrentWorkspace() + PATH_SEPARATOR + tv.Value;
QUrl url = QUrl::fromLocalFile(target);
QDesktopServices::openUrl(url);
}
@@ -1726,28 +1966,32 @@
{
return NULL;
}
//------------------------------------------------------------------------------
-void MainWindow::on_actionViewStash_triggered()
+const QIcon &MainWindow::getInternalIcon(const char* name)
{
- ui->stashTableView->setVisible(ui->actionViewStash->isChecked());
+ if(iconCache.contains(name))
+ return iconCache[name];
+
+ iconCache.insert(name, QIcon(name));
+ return iconCache[name];
}
//------------------------------------------------------------------------------
-void MainWindow::on_actionNewStash_triggered()
+void MainWindow::on_actionCreateStash_triggered()
{
QStringList stashed_files;
getSelectionFilenames(stashed_files, WorkspaceFile::TYPE_MODIFIED, true);
if(stashed_files.empty())
return;
QString stash_name;
bool revert = false;
- QString checkbox_text = tr("Revert stashed files");
- if(!CommitDialog::run(this, tr("Stash Changes"), stashed_files, stash_name, 0, true, &checkbox_text, &revert) || stashed_files.empty())
+
+ if(!CommitDialog::runStashNew(this, stashed_files, stash_name, revert) || stashed_files.empty())
return;
stash_name = stash_name.trimmed();
if(stash_name.indexOf("\"")!=-1 || stash_name.isEmpty())
@@ -1774,11 +2018,14 @@
//------------------------------------------------------------------------------
void MainWindow::on_actionApplyStash_triggered()
{
QStringList stashes;
- getStashViewSelection(stashes);
+ getSelectionStashes(stashes);
+
+ if(stashes.empty())
+ return;
bool delete_stashes = false;
if(!FileActionDialog::run(this, tr("Apply Stash"), tr("The following stashes will be applied.")+"\n"+tr("Are you sure?"), stashes, tr("Delete after applying"), &delete_stashes))
return;
@@ -1813,11 +2060,11 @@
//------------------------------------------------------------------------------
void MainWindow::on_actionDeleteStash_triggered()
{
QStringList stashes;
- getStashViewSelection(stashes);
+ getSelectionStashes(stashes);
if(stashes.empty())
return;
if(!FileActionDialog::run(this, tr("Delete Stashes"), tr("The following stashes will be deleted.")+"\n"+tr("Are you sure?"), stashes))
@@ -1841,11 +2088,11 @@
//------------------------------------------------------------------------------
void MainWindow::on_actionDiffStash_triggered()
{
QStringList stashes;
- getStashViewSelection(stashes);
+ getSelectionStashes(stashes);
if(stashes.length() != 1)
return;
stashmap_t::iterator id_it = getWorkspace().getStashes().find(*stashes.begin());
@@ -1886,21 +2133,21 @@
}
//------------------------------------------------------------------------------
void MainWindow::on_fileTableView_customContextMenuRequested(const QPoint &pos)
{
- QPoint gpos = QCursor::pos();
+ QPoint gpos = QCursor::pos() + QPoint(1, 1);
#ifdef Q_OS_WIN
if(qApp->keyboardModifiers() & Qt::SHIFT)
{
ui->fileTableView->selectionModel()->select(ui->fileTableView->indexAt(pos), QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Rows);
QStringList fnames;
getSelectionFilenames(fnames);
if(fnames.size()==1)
{
- QString fname = getCurrentWorkspace() + PATH_SEP + fnames[0];
+ QString fname = getCurrentWorkspace() + PATH_SEPARATOR + fnames[0];
fname = QDir::toNativeSeparators(fname);
if(ShowExplorerMenu((HWND)winId(), fname, gpos))
refresh();
}
}
@@ -1913,10 +2160,42 @@
menu->addActions(ui->fileTableView->actions());
menu->popup(gpos);
}
}
+
+//------------------------------------------------------------------------------
+void MainWindow::on_workspaceTreeView_customContextMenuRequested(const QPoint &)
+{
+ QModelIndexList indices = ui->workspaceTreeView->selectionModel()->selectedIndexes();
+
+ if(indices.empty())
+ return;
+
+ QMenu *menu = 0;
+
+ // Get first selected item
+ const QModelIndex &mi = indices.first();
+ QVariant data = getWorkspace().getTreeModel().data(mi, ROLE_WORKSPACE_ITEM);
+ Q_ASSERT(data.isValid());
+ WorkspaceItem tv = data.value();
+
+ if(tv.Type == WorkspaceItem::TYPE_FOLDER || tv.Type == WorkspaceItem::TYPE_WORKSPACE)
+ menu = menuWorkspace;
+ else if (tv.Type == WorkspaceItem::TYPE_STASH || tv.Type == WorkspaceItem::TYPE_STASHES)
+ menu = menuStashes;
+ else if (tv.Type == WorkspaceItem::TYPE_TAG || tv.Type == WorkspaceItem::TYPE_TAGS)
+ menu = menuTags;
+ else if (tv.Type == WorkspaceItem::TYPE_BRANCH || tv.Type == WorkspaceItem::TYPE_BRANCHES)
+ menu = menuBranches;
+
+ if(menu)
+ {
+ QPoint pos = QCursor::pos() + QPoint(1, 1);
+ menu->popup(pos);
+ }
+}
//------------------------------------------------------------------------------
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
// Ignore drops from the same window
@@ -2014,10 +2293,12 @@
//------------------------------------------------------------------------------
void MainWindow::MainWinUICallback::beginProcess(const QString& text)
{
Q_ASSERT(mainWindow);
mainWindow->ui->statusBar->showMessage(text);
+ mainWindow->lblTags->setHidden(true);
+ mainWindow->lblRevision->setHidden(true);
mainWindow->progressBar->setHidden(false);
QCoreApplication::processEvents();
}
//------------------------------------------------------------------------------
@@ -2031,14 +2312,168 @@
//------------------------------------------------------------------------------
void MainWindow::MainWinUICallback::endProcess()
{
Q_ASSERT(mainWindow);
mainWindow->ui->statusBar->clearMessage();
+ mainWindow->lblTags->setHidden(false);
+ mainWindow->lblRevision->setHidden(false);
mainWindow->progressBar->setHidden(true);
QCoreApplication::processEvents();
}
//------------------------------------------------------------------------------
QMessageBox::StandardButton MainWindow::MainWinUICallback::Query(const QString &title, const QString &query, QMessageBox::StandardButtons buttons)
{
return DialogQuery(mainWindow, title, query, buttons);
}
+
+//------------------------------------------------------------------------------
+void MainWindow::updateRevision(const QString &revision)
+{
+ const QString latest = tr(REVISION_LATEST);
+ QString defaultval = latest;
+
+ if(!revision.isEmpty())
+ defaultval = revision;
+
+ QString selected_revision = RevisionDialog::runUpdate(this, tr("Update workspace"), versionList, defaultval).trimmed();
+
+ if(selected_revision.isEmpty())
+ return;
+ else if(selected_revision == latest)
+ selected_revision = ""; // Empty revision is "latest"
+
+ QStringList res;
+
+ // Do test update
+ if(!fossil().updateRepository(res, selected_revision, true))
+ return;
+
+ if(res.length()==0)
+ return;
+
+ QStringMap kv;
+ ParseProperties(kv, res, ':');
+ // If no changes exit
+ if(kv.contains("changes") && kv["changes"].indexOf("None.")!=-1)
+ return;
+
+ if(!FileActionDialog::run(this, tr("Update"), tr("The following files will be updated.")+"\n"+tr("Are you sure?"), res))
+ return;
+
+ // Do update
+ fossil().updateRepository(res, selected_revision, false);
+ refresh();
+}
+
+//------------------------------------------------------------------------------
+void MainWindow::on_actionCreateTag_triggered()
+{
+ // Default to current revision
+ QString revision = fossil().getCurrentRevision();
+
+ QString name;
+ if(!RevisionDialog::runNewTag(this, tr("Create Tag"), versionList, revision, revision, name))
+ return;
+
+ if(name.isEmpty() || getWorkspace().getTags().contains(name) || getWorkspace().getBranches().contains(name))
+ {
+ QMessageBox::critical(this, tr("Error"), tr("Invalid name."), QMessageBox::Ok );
+ return;
+ }
+
+ fossil().tagNew(name, revision);
+ refresh();
+}
+
+//------------------------------------------------------------------------------
+void MainWindow::on_actionDeleteTag_triggered()
+{
+ if(selectedTags.size()!=1)
+ return;
+
+ const QString &tagname = selectedTags.first();
+
+ if(QMessageBox::Yes != DialogQuery(this, tr("Delete Tag"), tr("Are you sure want to delete the tag '%0' ?").arg(tagname)))
+ return;
+
+ Q_ASSERT(getWorkspace().getTags().contains(tagname));
+
+ const QString &revision = getWorkspace().getTags()[tagname];
+
+ fossil().tagDelete(tagname, revision);
+ refresh();
+}
+
+//------------------------------------------------------------------------------
+void MainWindow::on_actionCreateBranch_triggered()
+{
+ // Default to current revision
+ QString revision = fossil().getCurrentRevision();
+
+ QString branch_name;
+ if(!RevisionDialog::runNewTag(this, tr("Create Branch"), versionList, revision, revision, branch_name))
+ return;
+
+ if(branch_name.isEmpty() || getWorkspace().getTags().contains(branch_name) || getWorkspace().getBranches().contains(branch_name))
+ {
+ QMessageBox::critical(this, tr("Error"), tr("Invalid name."), QMessageBox::Ok );
+ return;
+ }
+
+ if(!fossil().branchNew(branch_name, revision, false))
+ return;
+
+ // Update to this branch.
+ updateRevision(branch_name);
+}
+//------------------------------------------------------------------------------
+void MainWindow::MergeRevision(const QString &defaultRevision)
+{
+ QStringList res;
+ QString revision = defaultRevision;
+
+ bool integrate = false;
+ bool force = false;
+ revision = RevisionDialog::runMerge(this, tr("Merge Branch"), versionList, revision, integrate, force);
+
+ if(revision.isEmpty())
+ return;
+
+ // Do test merge
+ if(!fossil().branchMerge(res, revision, integrate, force, true))
+ return;
+
+ if(!FileActionDialog::run(this, tr("Merge"), tr("The following changes will be applied.")+"\n"+tr("Are you sure?"), res))
+ return;
+
+ // Do update
+ fossil().branchMerge(res, revision, integrate, force, false);
+
+ log(tr("Merge completed. Don't forget to commit!")+"\n");
+
+ refresh();
+}
+
+//------------------------------------------------------------------------------
+void MainWindow::on_actionMergeBranch_triggered()
+{
+ QString revision;
+
+ if(!selectedBranches.isEmpty())
+ revision = selectedBranches.first();
+ MergeRevision(revision);
+}
+
+//------------------------------------------------------------------------------
+void MainWindow::onSearchBoxTextChanged(const QString &)
+{
+ updateFileView();
+}
+
+//------------------------------------------------------------------------------
+void MainWindow::onSearch()
+{
+ searchBox->selectAll();
+ searchBox->setFocus();
+}
+
Index: src/MainWindow.h
==================================================================
--- src/MainWindow.h
+++ src/MainWindow.h
@@ -1,11 +1,12 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
-#include "SettingsDialog.h"
+#include
+#include "Settings.h"
#include "Workspace.h"
namespace Ui {
class MainWindow;
}
@@ -26,38 +27,40 @@
private:
bool refresh();
void scanWorkspace();
void applySettings();
void updateSettings();
+ void updateRevision(const QString& revision);
const QString &getCurrentWorkspace();
void setCurrentWorkspace(const QString &workspace);
void log(const QString &text, bool isHTML=false);
void setStatus(const QString &text);
bool uiRunning() const;
void getSelectionFilenames(QStringList &filenames, int includeMask=WorkspaceFile::TYPE_ALL, bool allIfEmpty=false);
void getFileViewSelection(QStringList &filenames, int includeMask=WorkspaceFile::TYPE_ALL, bool allIfEmpty=false);
void getDirViewSelection(QStringList &filenames, int includeMask=WorkspaceFile::TYPE_ALL, bool allIfEmpty=false);
- void getStashViewSelection(QStringList &stashNames, bool allIfEmpty=false);
+ void getSelectionStashes(QStringList &stashNames);
void getSelectionPaths(stringset_t &paths);
void getAllFilenames(QStringList &filenames, int includeMask=WorkspaceFile::TYPE_ALL);
bool startUI();
void stopUI();
void enableActions(bool on);
void addWorkspace(const QString &dir);
void rebuildRecent();
bool openWorkspace(const QString &path);
void loadFossilSettings();
- QString getFossilHttpAddress();
- void updateDirView();
+ void updateWorkspaceView();
void updateFileView();
- void updateStashView();
void selectRootDir();
+ void MergeRevision(const QString& defaultRevision);
+
void fossilBrowse(const QString &fossilUrl);
void dragEnterEvent(class QDragEnterEvent *event);
void dropEvent(class QDropEvent *event);
void setBusy(bool busy);
virtual QMenu *createPopupMenu();
+ const QIcon& getInternalIcon(const char *name);
enum ViewMode
{
VIEWMODE_LIST,
VIEWMODE_TREE
@@ -68,10 +71,12 @@
// Use a different naming scheme to prevent warnings from Qt's automatic signaling
void onOpenRecent();
void onWorkspaceTreeViewSelectionChanged(const class QItemSelection &selected, const class QItemSelection &deselected);
void onFileViewDragOut();
void onAbort();
+ void onSearchBoxTextChanged(const QString &text);
+ void onSearch();
// Designer slots
void on_actionRefresh_triggered();
void on_actionDiff_triggered();
void on_actionFossilUI_triggered();
@@ -92,28 +97,35 @@
void on_actionRename_triggered();
void on_actionUndo_triggered();
void on_actionAbout_triggered();
void on_actionUpdate_triggered();
void on_actionSettings_triggered();
+ void on_actionFossilSettings_triggered();
void on_actionViewUnchanged_triggered();
void on_actionViewModified_triggered();
void on_actionViewUnknown_triggered();
void on_actionViewIgnored_triggered();
+ void on_actionViewAll_triggered();
void on_actionViewAsList_triggered();
+ void on_actionViewAsFolders_triggered();
void on_actionOpenFolder_triggered();
void on_actionRenameFolder_triggered();
void on_actionNewRepository_triggered();
void on_actionOpenRepository_triggered();
void on_actionCloseRepository_triggered();
void on_actionCloneRepository_triggered();
- void on_actionViewStash_triggered();
- void on_actionNewStash_triggered();
+ void on_actionCreateStash_triggered();
void on_actionApplyStash_triggered();
void on_actionDeleteStash_triggered();
void on_actionDiffStash_triggered();
void on_textBrowser_customContextMenuRequested(const QPoint &pos);
void on_fileTableView_customContextMenuRequested(const QPoint &pos);
+ void on_workspaceTreeView_customContextMenuRequested(const QPoint &pos);
+ void on_actionCreateTag_triggered();
+ void on_actionDeleteTag_triggered();
+ void on_actionCreateBranch_triggered();
+ void on_actionMergeBranch_triggered();
private:
class MainWinUICallback : public UICallback
{
public:
@@ -141,16 +153,32 @@
enum
{
MAX_RECENT=5
};
+ typedef QMap icon_map_t;
+
Ui::MainWindow *ui;
+ QFileIconProvider iconProvider;
+ icon_map_t iconCache;
class QAction *recentWorkspaceActs[MAX_RECENT];
class QProgressBar *progressBar;
+ class QLabel *lblRevision;
+ class QLabel *lblTags;
class QShortcut *abortShortcut;
+ class SearchBox *searchBox;
+ class QShortcut *searchShortcut;
+ QMenu *menuWorkspace;
+ QMenu *menuStashes;
+ QMenu *menuTags;
+ QMenu *menuBranches;
+
bool operationAborted;
stringset_t selectedDirs; // The directory selected in the tree
+ QStringList selectedTags;
+ QStringList selectedBranches;
+ QStringList versionList;
Workspace workspace;
Workspace & getWorkspace() { return workspace; }
Fossil & fossil() { return workspace.fossil(); }
ADDED src/RevisionDialog.cpp
Index: src/RevisionDialog.cpp
==================================================================
--- /dev/null
+++ src/RevisionDialog.cpp
@@ -0,0 +1,92 @@
+#include "RevisionDialog.h"
+#include "ui_RevisionDialog.h"
+#include "Utils.h"
+
+//-----------------------------------------------------------------------------
+RevisionDialog::RevisionDialog(QWidget *parent, const QStringList &completions, const QString &defaultValue) :
+ QDialog(parent),
+ ui(new Ui::RevisionDialog),
+ completer(completions, parent)
+{
+ ui->setupUi(this);
+ ui->cmbRevision->setCompleter(&completer);
+
+ ui->cmbRevision->addItems(completions);
+
+ if(!defaultValue.isEmpty())
+ ui->cmbRevision->setCurrentText(defaultValue);
+}
+
+//-----------------------------------------------------------------------------
+RevisionDialog::~RevisionDialog()
+{
+ delete ui;
+}
+
+//-----------------------------------------------------------------------------
+QString RevisionDialog::runUpdate(QWidget *parent, const QString &title, const QStringList &completions, const QString &defaultValue)
+{
+ RevisionDialog dlg(parent, completions, defaultValue);
+ dlg.setWindowTitle(title);
+ dlg.ui->lblName->setVisible(false);
+ dlg.ui->lineName->setVisible(false);
+ dlg.ui->lblIntegrate->setVisible(false);
+ dlg.ui->chkIntegrate->setVisible(false);
+ dlg.ui->lblForce->setVisible(false);
+ dlg.ui->chkForce->setVisible(false);
+
+ dlg.adjustSize();
+
+ if(dlg.exec() != QDialog::Accepted)
+ return QString("");
+ return dlg.ui->cmbRevision->currentText().trimmed();
+}
+
+//-----------------------------------------------------------------------------
+QString RevisionDialog::runMerge(QWidget *parent, const QString &title, const QStringList &completions, const QString &defaultValue, bool &integrate, bool &force)
+{
+ RevisionDialog dlg(parent, completions, defaultValue);
+ dlg.setWindowTitle(title);
+ dlg.ui->lblName->setVisible(false);
+ dlg.ui->lineName->setVisible(false);
+ dlg.ui->lblIntegrate->setVisible(true);
+ dlg.ui->chkIntegrate->setVisible(true);
+ dlg.ui->chkIntegrate->setChecked(integrate);
+ dlg.ui->lblForce->setVisible(true);
+ dlg.ui->chkForce->setVisible(true);
+ dlg.ui->chkForce->setChecked(force);
+
+ dlg.adjustSize();
+
+ if(dlg.exec() != QDialog::Accepted)
+ return QString("");
+
+ integrate = dlg.ui->chkIntegrate->checkState() == Qt::Checked;
+ force = dlg.ui->chkForce->checkState() == Qt::Checked;
+
+ return dlg.ui->cmbRevision->currentText().trimmed();
+}
+
+
+//-----------------------------------------------------------------------------
+bool RevisionDialog::runNewTag(QWidget *parent, const QString &title, const QStringList &completions, const QString &defaultValue, QString &revision, QString &name)
+{
+ RevisionDialog dlg(parent, completions, defaultValue);
+ dlg.setWindowTitle(title);
+
+ dlg.ui->lblName->setVisible(true);
+ dlg.ui->lineName->setVisible(true);
+ dlg.ui->lblIntegrate->setVisible(false);
+ dlg.ui->chkIntegrate->setVisible(false);
+ dlg.ui->lblForce->setVisible(false);
+ dlg.ui->chkForce->setVisible(false);
+
+ dlg.adjustSize();
+
+ if(dlg.exec() != QDialog::Accepted)
+ return false;
+
+ revision = dlg.ui->cmbRevision->currentText().trimmed();
+ name = dlg.ui->lineName->text().trimmed();
+ return true;
+}
ADDED src/RevisionDialog.h
Index: src/RevisionDialog.h
==================================================================
--- /dev/null
+++ src/RevisionDialog.h
@@ -0,0 +1,28 @@
+#ifndef REVISIONDIALOG_H
+#define REVISIONDIALOG_H
+
+#include
+#include
+
+namespace Ui {
+ class RevisionDialog;
+}
+
+class RevisionDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit RevisionDialog(QWidget *parent, const QStringList &completions, const QString &defaultValue);
+ ~RevisionDialog();
+
+ static QString runUpdate(QWidget *parent, const QString &title, const QStringList &completions, const QString &defaultValue);
+ static QString runMerge(QWidget* parent, const QString& title, const QStringList& completions, const QString& defaultValue, bool& integrate, bool& force);
+ static bool runNewTag(QWidget *parent, const QString &title, const QStringList &completions, const QString &defaultValue, QString &revision, QString &name);
+
+private:
+ Ui::RevisionDialog *ui;
+ QCompleter completer;
+};
+
+#endif // REVISIONDIALOG_H
ADDED src/SearchBox.cpp
Index: src/SearchBox.cpp
==================================================================
--- /dev/null
+++ src/SearchBox.cpp
@@ -0,0 +1,24 @@
+#include "SearchBox.h"
+#include
+
+SearchBox::SearchBox(QWidget *parent) : QLineEdit(parent)
+{
+}
+
+SearchBox::~SearchBox()
+{
+
+}
+
+void SearchBox::keyPressEvent(QKeyEvent *event)
+{
+ // Clear text on escape
+ if(event->key() == Qt::Key_Escape)
+ {
+ setText("");
+ clearFocus();
+ }
+ else
+ QLineEdit::keyPressEvent(event);
+}
+
ADDED src/SearchBox.h
Index: src/SearchBox.h
==================================================================
--- /dev/null
+++ src/SearchBox.h
@@ -0,0 +1,23 @@
+#ifndef SEARCHBOX_H
+#define SEARCHBOX_H
+
+#include
+
+class SearchBox : public QLineEdit
+{
+ Q_OBJECT
+public:
+ explicit SearchBox(QWidget* parent=0);
+ ~SearchBox();
+
+signals:
+
+public slots:
+
+protected:
+ void keyPressEvent(QKeyEvent *event);
+
+};
+
+
+#endif // SEARCHBOX_H
ADDED src/Settings.cpp
Index: src/Settings.cpp
==================================================================
--- /dev/null
+++ src/Settings.cpp
@@ -0,0 +1,124 @@
+#include "Settings.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+///////////////////////////////////////////////////////////////////////////////
+Settings::Settings(bool portableMode) : store(0)
+{
+ Mappings.insert(FOSSIL_SETTING_GDIFF_CMD, Setting("", Setting::TYPE_FOSSIL_GLOBAL));
+ Mappings.insert(FOSSIL_SETTING_GMERGE_CMD, Setting("", Setting::TYPE_FOSSIL_GLOBAL));
+ Mappings.insert(FOSSIL_SETTING_PROXY_URL, Setting("", Setting::TYPE_FOSSIL_GLOBAL));
+ Mappings.insert(FOSSIL_SETTING_HTTP_PORT, Setting("", Setting::TYPE_FOSSIL_GLOBAL));
+
+ Mappings.insert(FOSSIL_SETTING_IGNORE_GLOB, Setting("", Setting::TYPE_FOSSIL_LOCAL));
+ Mappings.insert(FOSSIL_SETTING_CRNL_GLOB, Setting("", Setting::TYPE_FOSSIL_LOCAL));
+ Mappings.insert(FOSSIL_SETTING_REMOTE_URL, Setting("off", Setting::TYPE_FOSSIL_COMMAND));
+
+ // Go into portable mode when explicitly requested or if a config file exists next to the executable
+ QString ini_path = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + QDir::separator() + QCoreApplication::applicationName() + ".ini");
+ if( portableMode || QFile::exists(ini_path))
+ store = new QSettings(ini_path, QSettings::IniFormat);
+ else
+ {
+ // Linux: ~/.config/organizationName/applicationName.conf
+ // Windows: HKEY_CURRENT_USER\Software\organizationName\Fuel
+ store = new QSettings(QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
+ }
+ Q_ASSERT(store);
+
+ if(!HasValue(FUEL_SETTING_FILE_DBLCLICK))
+ SetValue(FUEL_SETTING_FILE_DBLCLICK, 0);
+ if(!HasValue(FUEL_SETTING_LANGUAGE) && SupportsLang(QLocale::system().name()))
+ SetValue(FUEL_SETTING_LANGUAGE, QLocale::system().name());
+ if(!HasValue(FUEL_SETTING_WEB_BROWSER))
+ SetValue(FUEL_SETTING_WEB_BROWSER, 0);
+
+ ApplyEnvironment();
+}
+
+//-----------------------------------------------------------------------------
+Settings::~Settings()
+{
+ Q_ASSERT(store);
+ delete store;
+}
+
+//-----------------------------------------------------------------------------
+void Settings::ApplyEnvironment()
+{
+ QString lang_id = GetValue(FUEL_SETTING_LANGUAGE).toString();
+#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
+ QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8"));
+#endif
+ if(!InstallLang(lang_id))
+ SetValue(FUEL_SETTING_LANGUAGE, "en_US");
+}
+
+//-----------------------------------------------------------------------------
+bool Settings::InstallLang(const QString &langId)
+{
+ if(langId == "en_US")
+ {
+ QCoreApplication::instance()->removeTranslator(&translator);
+ return true;
+ }
+
+ QString locale_path = QString(":intl/intl/%0.qm").arg(langId);
+ if(!translator.load(locale_path))
+ return false;
+
+ Q_ASSERT(!translator.isEmpty());
+ QCoreApplication::instance()->installTranslator(&translator);
+
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+bool Settings::HasValue(const QString &name) const
+{
+ return store->contains(name);
+}
+
+//-----------------------------------------------------------------------------
+const QVariant Settings::GetValue(const QString &name)
+{
+ if(!HasValue(name))
+ return QVariant();
+ return store->value(name);
+}
+
+//-----------------------------------------------------------------------------
+void Settings::SetValue(const QString &name, const QVariant &value)
+{
+ store->setValue(name, value);
+}
+
+//-----------------------------------------------------------------------------
+QVariant &Settings::GetFossilValue(const QString &name)
+{
+ mappings_t::iterator it=Mappings.find(name);
+ Q_ASSERT(it!=Mappings.end());
+ return it.value().Value;
+}
+
+//-----------------------------------------------------------------------------
+void Settings::SetFossilValue(const QString &name, const QVariant &value)
+{
+ mappings_t::iterator it=Mappings.find(name);
+ Q_ASSERT(it!=Mappings.end());
+ it->Value = value;
+}
+
+//-----------------------------------------------------------------------------
+bool Settings::SupportsLang(const QString &langId) const
+{
+ QString locale_path = QString(":intl/intl/%0.qm").arg(langId);
+ QResource res(locale_path);
+ return res.isValid();
+}
ADDED src/Settings.h
Index: src/Settings.h
==================================================================
--- /dev/null
+++ src/Settings.h
@@ -0,0 +1,75 @@
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+#include
+#include
+#include
+
+#define FUEL_SETTING_FOSSIL_PATH "FossilPath"
+#define FUEL_SETTING_COMMIT_MSG "CommitMsgHistory"
+#define FUEL_SETTING_FILE_DBLCLICK "FileDblClickAction"
+#define FUEL_SETTING_LANGUAGE "Language"
+#define FUEL_SETTING_WEB_BROWSER "WebBrowser"
+
+#define FOSSIL_SETTING_GDIFF_CMD "gdiff-command"
+#define FOSSIL_SETTING_GMERGE_CMD "gmerge-command"
+#define FOSSIL_SETTING_PROXY_URL "proxy"
+#define FOSSIL_SETTING_IGNORE_GLOB "ignore-glob"
+#define FOSSIL_SETTING_CRNL_GLOB "crnl-glob"
+#define FOSSIL_SETTING_REMOTE_URL "remote-url"
+#define FOSSIL_SETTING_HTTP_PORT "http-port"
+
+
+enum FileDblClickAction
+{
+ FILE_DLBCLICK_ACTION_DIFF,
+ FILE_DLBCLICK_ACTION_OPEN,
+ FILE_DLBCLICK_ACTION_OPENCONTAINING,
+ FILE_DLBCLICK_ACTION_MAX
+};
+
+struct Settings
+{
+ struct Setting
+ {
+ enum SettingType
+ {
+ TYPE_FOSSIL_GLOBAL,
+ TYPE_FOSSIL_LOCAL,
+ TYPE_FOSSIL_COMMAND
+ };
+
+ Setting(QVariant value, SettingType type) : Value(value), Type(type)
+ {}
+ QVariant Value;
+ SettingType Type;
+ };
+ typedef QMap mappings_t;
+
+
+ Settings(bool portableMode = false);
+ ~Settings();
+
+ void ApplyEnvironment();
+
+ // App configuration access
+ class QSettings * GetStore() { return store; }
+ bool HasValue(const QString &name) const; // store->contains(FUEL_SETTING_FOSSIL_PATH)
+ const QVariant GetValue(const QString &name); // settings.store->value
+ void SetValue(const QString &name, const QVariant &value); // settings.store->value
+
+ // Fossil configuration access
+ QVariant & GetFossilValue(const QString &name);
+ void SetFossilValue(const QString &name, const QVariant &value);
+ mappings_t & GetMappings() { return Mappings; }
+
+ bool SupportsLang(const QString &langId) const;
+ bool InstallLang(const QString &langId);
+private:
+ mappings_t Mappings;
+ class QSettings *store;
+ QTranslator translator;
+};
+
+
+#endif // SETTINGS_H
Index: src/SettingsDialog.cpp
==================================================================
--- src/SettingsDialog.cpp
+++ src/SettingsDialog.cpp
@@ -1,39 +1,10 @@
#include "SettingsDialog.h"
#include "ui_SettingsDialog.h"
-#include
#include "Utils.h"
-#include
-#include
#include
-#include
-#include
-#include
-
-
-///////////////////////////////////////////////////////////////////////////////
-QString SettingsDialog::SelectExe(QWidget *parent, const QString &description)
-{
- QString filter(tr("Applications"));
-#ifdef Q_OS_WIN
- filter += " (*.exe)";
-#else
- filter += " (*)";
-#endif
- QString path = QFileDialog::getOpenFileName(
- parent,
- description,
- QString(),
- filter,
- &filter);
-
- if(!QFile::exists(path))
- return QString();
-
- return path;
-}
///////////////////////////////////////////////////////////////////////////////
SettingsDialog::SettingsDialog(QWidget *parent, Settings &_settings) :
QDialog(parent, Qt::Sheet),
ui(new Ui::SettingsDialog),
@@ -52,11 +23,10 @@
// App Settings
ui->lineFossilPath->setText(QDir::toNativeSeparators(settings->GetValue(FUEL_SETTING_FOSSIL_PATH).toString()));
ui->cmbDoubleClickAction->setCurrentIndex(settings->GetValue(FUEL_SETTING_FILE_DBLCLICK).toInt());
ui->cmbFossilBrowser->setCurrentIndex(settings->GetValue(FUEL_SETTING_WEB_BROWSER).toInt());
- ui->lineUIPort->setText(settings->GetValue(FUEL_SETTING_HTTP_PORT).toString());
// Initialize language combo
foreach(const LangMap &m, langMap)
ui->cmbActiveLanguage->addItem(m.name);
@@ -64,19 +34,10 @@
// Select current language
ui->cmbActiveLanguage->setCurrentIndex(
ui->cmbActiveLanguage->findText(
LangIdToName(lang)));
- // Global Settings
- ui->lineGDiffCommand->setText(settings->GetFossilValue(FOSSIL_SETTING_GDIFF_CMD).toString());
- ui->lineGMergeCommand->setText(settings->GetFossilValue(FOSSIL_SETTING_GMERGE_CMD).toString());
- ui->lineProxy->setText(settings->GetFossilValue(FOSSIL_SETTING_PROXY_URL).toString());
-
- // Repository Settings
- ui->lineRemoteURL->setText(settings->GetFossilValue(FOSSIL_SETTING_REMOTE_URL).toString());
- ui->lineIgnore->setText(settings->GetFossilValue(FOSSIL_SETTING_IGNORE_GLOB).toString());
- ui->lineIgnoreCRNL->setText(settings->GetFossilValue(FOSSIL_SETTING_CRNL_GLOB).toString());
}
//-----------------------------------------------------------------------------
SettingsDialog::~SettingsDialog()
{
@@ -95,29 +56,19 @@
{
settings->SetValue(FUEL_SETTING_FOSSIL_PATH, QDir::fromNativeSeparators(ui->lineFossilPath->text()));
Q_ASSERT(ui->cmbDoubleClickAction->currentIndex()>=FILE_DLBCLICK_ACTION_DIFF && ui->cmbDoubleClickAction->currentIndex()SetValue(FUEL_SETTING_FILE_DBLCLICK, ui->cmbDoubleClickAction->currentIndex());
settings->SetValue(FUEL_SETTING_WEB_BROWSER, ui->cmbFossilBrowser->currentIndex());
- settings->SetValue(FUEL_SETTING_HTTP_PORT, ui->lineUIPort->text());
Q_ASSERT(settings->HasValue(FUEL_SETTING_LANGUAGE));
QString curr_langid = settings->GetValue(FUEL_SETTING_LANGUAGE).toString();
QString new_langid = LangNameToId(ui->cmbActiveLanguage->currentText());
Q_ASSERT(!new_langid.isEmpty());
settings->SetValue(FUEL_SETTING_LANGUAGE, new_langid);
if(curr_langid != new_langid)
QMessageBox::information(this, tr("Restart required"), tr("The language change will take effect after restarting the application"), QMessageBox::Ok);
-
- settings->SetFossilValue(FOSSIL_SETTING_GDIFF_CMD, ui->lineGDiffCommand->text());
- settings->SetFossilValue(FOSSIL_SETTING_GMERGE_CMD, ui->lineGMergeCommand->text());
- settings->SetFossilValue(FOSSIL_SETTING_PROXY_URL, ui->lineProxy->text());
-
- settings->SetFossilValue(FOSSIL_SETTING_REMOTE_URL, ui->lineRemoteURL->text());
- settings->SetFossilValue(FOSSIL_SETTING_IGNORE_GLOB, ui->lineIgnore->text());
- settings->SetFossilValue(FOSSIL_SETTING_CRNL_GLOB, ui->lineIgnoreCRNL->text());
-
settings->ApplyEnvironment();
}
//-----------------------------------------------------------------------------
@@ -126,26 +77,10 @@
QString path = SelectExe(this, tr("Select Fossil executable"));
if(!path.isEmpty())
ui->lineFossilPath->setText(QDir::toNativeSeparators(path));
}
-//-----------------------------------------------------------------------------
-void SettingsDialog::on_btnSelectFossilGDiff_clicked()
-{
- QString path = SelectExe(this, tr("Select Graphical Diff application"));
- if(!path.isEmpty())
- ui->lineGDiffCommand->setText(QDir::toNativeSeparators(path));
-}
-
-//-----------------------------------------------------------------------------
-void SettingsDialog::on_btnSelectGMerge_clicked()
-{
- QString path = SelectExe(this, tr("Select Graphical Merge application"));
- if(!path.isEmpty())
- ui->lineGMergeCommand->setText(path);
-}
-
//-----------------------------------------------------------------------------
void SettingsDialog::on_btnClearMessageHistory_clicked()
{
if(DialogQuery(this, tr("Clear Commit Message History"), tr("Are you sure you want to clear the commit message history?"))==QMessageBox::Yes)
settings->SetValue(FUEL_SETTING_COMMIT_MSG, QStringList());
@@ -184,122 +119,5 @@
return m.id;
}
return "";
}
-
-///////////////////////////////////////////////////////////////////////////////
-Settings::Settings(bool portableMode) : store(0)
-{
- Mappings.insert(FOSSIL_SETTING_GDIFF_CMD, Setting("", Setting::TYPE_FOSSIL_GLOBAL));
- Mappings.insert(FOSSIL_SETTING_GMERGE_CMD, Setting("", Setting::TYPE_FOSSIL_GLOBAL));
- Mappings.insert(FOSSIL_SETTING_PROXY_URL, Setting("", Setting::TYPE_FOSSIL_GLOBAL));
-
- Mappings.insert(FOSSIL_SETTING_IGNORE_GLOB, Setting("", Setting::TYPE_FOSSIL_LOCAL));
- Mappings.insert(FOSSIL_SETTING_CRNL_GLOB, Setting("", Setting::TYPE_FOSSIL_LOCAL));
- Mappings.insert(FOSSIL_SETTING_REMOTE_URL, Setting("off", Setting::TYPE_FOSSIL_COMMAND));
-
- // Go into portable mode when explicitly requested or if a config file exists next to the executable
- QString ini_path = QDir::toNativeSeparators(QCoreApplication::applicationDirPath() + QDir::separator() + QCoreApplication::applicationName() + ".ini");
- if( portableMode || QFile::exists(ini_path))
- store = new QSettings(ini_path, QSettings::IniFormat);
- else
- {
- // Linux: ~/.config/organizationName/applicationName.conf
- // Windows: HKEY_CURRENT_USER\Software\organizationName\Fuel
- store = new QSettings(QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
- }
- Q_ASSERT(store);
-
- if(!HasValue(FUEL_SETTING_FILE_DBLCLICK))
- SetValue(FUEL_SETTING_FILE_DBLCLICK, 0);
- if(!HasValue(FUEL_SETTING_LANGUAGE) && SupportsLang(QLocale::system().name()))
- SetValue(FUEL_SETTING_LANGUAGE, QLocale::system().name());
- if(!HasValue(FUEL_SETTING_WEB_BROWSER))
- SetValue(FUEL_SETTING_WEB_BROWSER, 0);
- if(!HasValue(FUEL_SETTING_HTTP_PORT))
- SetValue(FUEL_SETTING_HTTP_PORT, "8090");
-
- ApplyEnvironment();
-}
-
-//-----------------------------------------------------------------------------
-Settings::~Settings()
-{
- Q_ASSERT(store);
- delete store;
-}
-
-//-----------------------------------------------------------------------------
-void Settings::ApplyEnvironment()
-{
- QString lang_id = GetValue(FUEL_SETTING_LANGUAGE).toString();
-#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
- QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8"));
-#endif
- if(!InstallLang(lang_id))
- SetValue(FUEL_SETTING_LANGUAGE, "en_US");
-}
-
-//-----------------------------------------------------------------------------
-bool Settings::InstallLang(const QString &langId)
-{
- if(langId == "en_US")
- {
- QCoreApplication::instance()->removeTranslator(&translator);
- return true;
- }
-
- QString locale_path = QString(":intl/intl/%0.qm").arg(langId);
- if(!translator.load(locale_path))
- return false;
-
- Q_ASSERT(!translator.isEmpty());
- QCoreApplication::instance()->installTranslator(&translator);
-
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-bool Settings::HasValue(const QString &name) const
-{
- return store->contains(name);
-}
-
-//-----------------------------------------------------------------------------
-const QVariant Settings::GetValue(const QString &name)
-{
- if(!HasValue(name))
- return QVariant();
- return store->value(name);
-}
-
-//-----------------------------------------------------------------------------
-void Settings::SetValue(const QString &name, const QVariant &value)
-{
- store->setValue(name, value);
-}
-
-//-----------------------------------------------------------------------------
-QVariant &Settings::GetFossilValue(const QString &name)
-{
- mappings_t::iterator it=Mappings.find(name);
- Q_ASSERT(it!=Mappings.end());
- return it.value().Value;
-}
-
-//-----------------------------------------------------------------------------
-void Settings::SetFossilValue(const QString &name, const QVariant &value)
-{
- mappings_t::iterator it=Mappings.find(name);
- Q_ASSERT(it!=Mappings.end());
- it->Value = value;
-}
-
-//-----------------------------------------------------------------------------
-bool Settings::SupportsLang(const QString &langId) const
-{
- QString locale_path = QString(":intl/intl/%0.qm").arg(langId);
- QResource res(locale_path);
- return res.isValid();
-}
Index: src/SettingsDialog.h
==================================================================
--- src/SettingsDialog.h
+++ src/SettingsDialog.h
@@ -1,84 +1,14 @@
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H
#include
-#include
-#include
-#include
-
+#include "Settings.h"
namespace Ui {
class SettingsDialog;
}
-
-#define FUEL_SETTING_FOSSIL_PATH "FossilPath"
-#define FUEL_SETTING_COMMIT_MSG "CommitMsgHistory"
-#define FUEL_SETTING_FILE_DBLCLICK "FileDblClickAction"
-#define FUEL_SETTING_LANGUAGE "Language"
-#define FUEL_SETTING_WEB_BROWSER "WebBrowser"
-#define FUEL_SETTING_HTTP_PORT "HTTPPort"
-
-#define FOSSIL_SETTING_GDIFF_CMD "gdiff-command"
-#define FOSSIL_SETTING_GMERGE_CMD "gmerge-command"
-#define FOSSIL_SETTING_PROXY_URL "proxy"
-#define FOSSIL_SETTING_IGNORE_GLOB "ignore-glob"
-#define FOSSIL_SETTING_CRNL_GLOB "crnl-glob"
-#define FOSSIL_SETTING_REMOTE_URL "remote-url"
-
-
-enum FileDblClickAction
-{
- FILE_DLBCLICK_ACTION_DIFF,
- FILE_DLBCLICK_ACTION_OPEN,
- FILE_DLBCLICK_ACTION_OPENCONTAINING,
- FILE_DLBCLICK_ACTION_MAX
-};
-
-struct Settings
-{
- struct Setting
- {
- enum SettingType
- {
- TYPE_FOSSIL_GLOBAL,
- TYPE_FOSSIL_LOCAL,
- TYPE_FOSSIL_COMMAND
- };
-
- Setting(QVariant value, SettingType type) : Value(value), Type(type)
- {}
- QVariant Value;
- SettingType Type;
- };
- typedef QMap mappings_t;
-
-
- Settings(bool portableMode = false);
- ~Settings();
-
- void ApplyEnvironment();
-
- // App configuration access
- class QSettings * GetStore() { return store; }
- bool HasValue(const QString &name) const; // store->contains(FUEL_SETTING_FOSSIL_PATH)
- const QVariant GetValue(const QString &name); // settings.store->value
- void SetValue(const QString &name, const QVariant &value); // settings.store->value
-
- // Fossil configuration access
- QVariant & GetFossilValue(const QString &name);
- void SetFossilValue(const QString &name, const QVariant &value);
- mappings_t & GetMappings() { return Mappings; }
-
- bool SupportsLang(const QString &langId) const;
- bool InstallLang(const QString &langId);
-private:
- mappings_t Mappings;
- class QSettings *store;
- QTranslator translator;
-};
-
class SettingsDialog : public QDialog
{
Q_OBJECT
@@ -90,16 +20,13 @@
private slots:
void on_btnSelectFossil_clicked();
void on_buttonBox_accepted();
- void on_btnSelectFossilGDiff_clicked();
- void on_btnSelectGMerge_clicked();
void on_btnClearMessageHistory_clicked();
private:
- static QString SelectExe(QWidget *parent, const QString &description);
QString LangIdToName(const QString &id);
QString LangNameToId(const QString &name);
void CreateLangMap();
struct LangMap
Index: src/Utils.cpp
==================================================================
--- src/Utils.cpp
+++ src/Utils.cpp
@@ -1,8 +1,9 @@
#include "Utils.h"
#include
#include
+#include
///////////////////////////////////////////////////////////////////////////////
QMessageBox::StandardButton DialogQuery(QWidget *parent, const QString &title, const QString &query, QMessageBox::StandardButtons buttons)
{
QMessageBox mb(QMessageBox::Question, title, query, buttons, parent, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::Sheet );
@@ -27,10 +28,31 @@
for(int i=0; i
static bool DialogQueryText(QWidget *parent, const QString &title, const QString &query, QString &text, bool isPassword=false)
@@ -304,5 +326,66 @@
return bResult;
}
#endif
+//-----------------------------------------------------------------------------
+void ParseProperties(QStringMap &properties, const QStringList &lines, QChar separator)
+{
+ properties.clear();
+ foreach(QString l, lines)
+ {
+ l = l.trimmed();
+ int index = l.indexOf(separator);
+
+ QString key;
+ QString value;
+ if(index!=-1)
+ {
+ key = l.left(index).trimmed();
+ value = l.mid(index+1).trimmed();
+ }
+ else
+ key = l;
+
+ properties.insert(key, value);
+ }
+}
+
+
+//------------------------------------------------------------------------------
+void GetStandardItemTextRecursive(QString &name, const QStandardItem &item, const QChar &separator)
+{
+ if(item.parent())
+ {
+ GetStandardItemTextRecursive(name, *item.parent());
+ name.append(separator);
+ }
+
+ name.append(item.data(Qt::DisplayRole).toString());
+}
+
+//------------------------------------------------------------------------------
+void BuildNameToModelIndex(name_modelindex_map_t &map, const QStandardItem &item)
+{
+ QString name;
+ GetStandardItemTextRecursive(name, item);
+ map.insert(name, item.index());
+
+ for(int i=0; i
#include
+#include
+#include
#define COUNTOF(array) (sizeof(array)/sizeof(array[0]))
#define FOSSIL_CHECKOUT1 "_FOSSIL_"
#define FOSSIL_CHECKOUT2 ".fslckout"
#define FOSSIL_EXT "fossil"
@@ -11,10 +13,21 @@
QMessageBox::StandardButton DialogQuery(QWidget *parent, const QString &title, const QString &query, QMessageBox::StandardButtons buttons = QMessageBox::Yes|QMessageBox::No);
QString QuotePath(const QString &path);
QStringList QuotePaths(const QStringList &paths);
+QString SelectExe(QWidget *parent, const QString &description);
+
+
+typedef QMap name_modelindex_map_t;
+void GetStandardItemTextRecursive(QString &name, const QStandardItem &item, const QChar &separator='/');
+void BuildNameToModelIndex(name_modelindex_map_t &map, const QStandardItem &item);
+void BuildNameToModelIndex(name_modelindex_map_t &map, const QStandardItemModel &model);
+
+
+typedef QMap QStringMap;
+void ParseProperties(QStringMap &properties, const QStringList &lines, QChar separator=' ');
#ifdef Q_OS_WIN
bool ShowExplorerMenu(HWND hwnd, const QString &path, const QPoint &qpoint);
#endif
Index: src/Workspace.cpp
==================================================================
--- src/Workspace.cpp
+++ src/Workspace.cpp
@@ -15,10 +15,14 @@
foreach(WorkspaceFile *r, getFiles())
delete r;
getFiles().clear();
getPaths().clear();
+ stashMap.clear();
+ branchList.clear();
+ tags.clear();
+ isIntegrated = false;
}
//------------------------------------------------------------------------------
bool Workspace::scanDirectory(QFileInfoList &entries, const QString& dirPath, const QString &baseDir, const QString ignoreSpec, const bool &abort, UICallback &uiCallback)
{
@@ -114,12 +118,16 @@
{
QString line = (*line_it).trimmed();
if(line.length()==0)
continue;
- QString status_text = line.left(10).trimmed();
- QString fname = line.right(line.length() - 10).trimmed();
+ int space_index = line.indexOf(' ');
+ if(space_index==-1)
+ continue;
+
+ QString status_text = line.left(space_index);
+ QString fname = line.right(line.length() - space_index).trimmed();
WorkspaceFile::Type type = WorkspaceFile::TYPE_UNKNOWN;
// Generate a RepoFile for all non-existant fossil files
// or for all files if we skipped scanning the workspace
bool add_missing = !scan_files;
@@ -142,10 +150,12 @@
type = WorkspaceFile::TYPE_RENAMED;
else if(status_text=="UNCHANGED")
type = WorkspaceFile::TYPE_UNCHANGED;
else if(status_text=="CONFLICT")
type = WorkspaceFile::TYPE_CONFLICTED;
+ else if(status_text=="UPDATED_BY_MERGE" || status_text=="ADDED_BY_MERGE" || status_text=="ADDED_BY_INTEGRATE" || status_text=="UPDATED_BY_INTEGRATE")
+ type = WorkspaceFile::TYPE_MERGED;
// Filter unwanted file types
if( ((type & WorkspaceFile::TYPE_MODIFIED) && !scanModified) ||
((type & WorkspaceFile::TYPE_UNCHANGED) && !scanUnchanged))
{
@@ -176,11 +186,33 @@
QString path = rf->getPath();
getPaths().insert(path);
}
- // Load the stash
+ // Check if the repository needs integration
+ res.clear();
+ fossil().status(res);
+ isIntegrated = false;
+ foreach(const QString &l, res)
+ {
+ if(l.trimmed().indexOf("INTEGRATE")==0)
+ {
+ isIntegrated = true;
+ break;
+ }
+ }
+
+ // Load the stashes, branches and tags
fossil().stashList(getStashes());
+
+ fossil().branchList(branchList, branchList);
+
+ fossil().tagList(tags);
+ // Fossil includes the branches in the tag list
+ // So remove them
+ foreach(const QString &name, branchList)
+ tags.remove(name);
+
_done:
uiCallback.endProcess();
}
Index: src/Workspace.h
==================================================================
--- src/Workspace.h
+++ src/Workspace.h
@@ -4,10 +4,11 @@
#include
#include
#include
#include
#include
+#include "Utils.h"
#include "Fossil.h"
//////////////////////////////////////////////////////////////////////////
// WorkspaceFile
//////////////////////////////////////////////////////////////////////////
@@ -21,11 +22,12 @@
TYPE_ADDED = 1<<3,
TYPE_DELETED = 1<<4,
TYPE_MISSING = 1<<5,
TYPE_RENAMED = 1<<6,
TYPE_CONFLICTED = 1<<7,
- TYPE_MODIFIED = TYPE_EDITTED|TYPE_ADDED|TYPE_DELETED|TYPE_MISSING|TYPE_RENAMED|TYPE_CONFLICTED,
+ TYPE_MERGED = 1<<8,
+ TYPE_MODIFIED = TYPE_EDITTED|TYPE_ADDED|TYPE_DELETED|TYPE_MISSING|TYPE_RENAMED|TYPE_CONFLICTED|TYPE_MERGED,
TYPE_REPO = TYPE_UNCHANGED|TYPE_MODIFIED,
TYPE_ALL = TYPE_UNKNOWN|TYPE_REPO
};
WorkspaceFile(const QFileInfo &info, Type type, const QString &repoPath)
@@ -95,10 +97,14 @@
};
typedef QSet stringset_t;
+//////////////////////////////////////////////////////////////////////////
+// Workspace
+//////////////////////////////////////////////////////////////////////////
+
class Workspace
{
public:
~Workspace();
@@ -112,23 +118,28 @@
static bool scanDirectory(QFileInfoList &entries, const QString& dirPath, const QString &baseDir, const QString ignoreSpec, const bool& abort, UICallback &uiCallback);
void scanWorkspace(bool scanLocal, bool scanIgnored, bool scanModified, bool scanUnchanged, const QString &ignoreGlob, UICallback &uiCallback, bool &operationAborted);
QStandardItemModel &getFileModel() { return repoFileModel; }
- QStandardItemModel &getDirModel() { return repoDirModel; }
- QStandardItemModel &getStashModel() { return repoStashModel; }
+ QStandardItemModel &getTreeModel() { return repoTreeModel; }
+
filemap_t &getFiles() { return workspaceFiles; }
stringset_t &getPaths() { return pathSet; }
stashmap_t &getStashes() { return stashMap; }
+ QStringMap &getTags() { return tags; }
+ QStringList &getBranches() { return branchList; }
+ bool otherChanges() const { return isIntegrated; }
private:
Fossil bridge;
filemap_t workspaceFiles;
stringset_t pathSet;
stashmap_t stashMap;
+ QStringList branchList;
+ QStringMap tags;
+ bool isIntegrated;
QStandardItemModel repoFileModel;
- QStandardItemModel repoDirModel;
- QStandardItemModel repoStashModel;
+ QStandardItemModel repoTreeModel;
};
#endif // WORKSPACE_H
Index: src/main.cpp
==================================================================
--- src/main.cpp
+++ src/main.cpp
@@ -4,11 +4,11 @@
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
app.setApplicationName("Fuel");
app.setApplicationVersion("2.0.0");
- app.setOrganizationDomain("fuelscm.org");
+ app.setOrganizationDomain("fuel-scm.org");
app.setOrganizationName("Fuel-SCM");
#ifdef Q_OS_MACX
// Native OSX applications don't have menu icons
Index: ui/BrowserWidget.ui
==================================================================
--- ui/BrowserWidget.ui
+++ ui/BrowserWidget.ui
@@ -12,11 +12,20 @@
0
-
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
0
-
@@ -42,11 +51,11 @@
- :/icons/icons/Button Previous-01.png:/icons/icons/Button Previous-01.png
+ :/icons/icon-action-previous:/icons/icon-action-previous
Back
@@ -54,11 +63,11 @@
- :/icons/icons/Button Next-01.png:/icons/icons/Button Next-01.png
+ :/icons/icon-action-next:/icons/icon-action-next
Forward
@@ -66,11 +75,11 @@
- :/icons/icons/Button Refresh-01.png:/icons/icons/Button Refresh-01.png
+ :/icons/icon-action-refresh:/icons/icon-action-refresh
Refresh
@@ -78,11 +87,11 @@
- :/icons/icons/Button Close-01.png:/icons/icons/Button Close-01.png
+ :/icons/icon-action-stop:/icons/icon-action-stop
Stop
Index: ui/CommitDialog.ui
==================================================================
--- ui/CommitDialog.ui
+++ ui/CommitDialog.ui
@@ -8,11 +8,11 @@
0
0
400
- 300
+ 394
Commit
@@ -60,13 +60,76 @@
-
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ New branch
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ false
+
+
+
+ -
+
+
+ Branch name
+
+
+
+ -
+
+
+ Private branch
+
+
+
+
+
+
+ -
+
-
+ Revert stashed files
-
ADDED ui/FslSettingsDialog.ui
Index: ui/FslSettingsDialog.ui
==================================================================
--- /dev/null
+++ ui/FslSettingsDialog.ui
@@ -0,0 +1,300 @@
+
+
+ FslSettingsDialog
+
+
+ Qt::WindowModal
+
+
+
+ 0
+ 0
+ 457
+ 266
+
+
+
+ Fossil Settings
+
+
+
+ :/icons/icon-application:/icons/icon-application
+
+
+ true
+
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 100
+ 0
+
+
+
+ Graphical Diff
+
+
+
+ -
+
+
-
+
+
+ Path to graphical diff tool
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 24
+ 24
+
+
+
+ ...
+
+
+
+
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ Graphical Merge
+
+
+
+ -
+
+
-
+
+
+ Path to the graphical merge tool
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 24
+ 24
+
+
+
+ ...
+
+
+
+
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ HTTP Proxy
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ The URL of the HTTP proxy
+
+
+
+ -
+
+
+ HTTP Port
+
+
+
+ -
+
+
+ HTTP port to use for the Fossil web interface
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ A comma separated list of glob-style file patterns to exclude from Fossil's CR/NL consistency checking
+
+
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ Ignore CR/NL
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ A comma separated list of glob-style file/path patterns ignored in Fossil file operations
+
+
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ Ignore List
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ The remote url used to push/pull changes.
+URL style user names and passwords are also supported.
+For example http://username:password@server.com/fossil
+
+
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ Remote Url
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ FslSettingsDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ FslSettingsDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
Index: ui/MainWindow.ui
==================================================================
--- ui/MainWindow.ui
+++ ui/MainWindow.ui
@@ -15,12 +15,12 @@
Fuel
-
- :/icons/icons/Battery-01.png:/icons/icons/Battery-01.png
+
+ :/icons/icon-application:/icons/icon-application
true
@@ -64,11 +64,11 @@
20
0
- Qt::ActionsContextMenu
+ Qt::CustomContextMenu
QAbstractItemView::NoEditTriggers
@@ -76,15 +76,12 @@
QAbstractItemView::SelectItems
- true
+ false
-
- true
-
false
@@ -138,48 +135,10 @@
30
-
-
-
- 20
- 0
-
-
-
- Qt::ActionsContextMenu
-
-
- QAbstractItemView::NoEditTriggers
-
-
- true
-
-
- QAbstractItemView::SelectRows
-
-
- false
-
-
- true
-
-
- false
-
-
- false
-
-
- true
-
-
- false
-
-
0
@@ -188,11 +147,11 @@
QTabWidget::South
- 1
+ 0
Log
@@ -261,11 +220,11 @@
0
0
865
- 22
+ 23
+
+
Main Toolbar
@@ -341,12 +321,10 @@
-
-
@@ -354,15 +332,15 @@
-
- :/icons/icons/Button Refresh-01.png:/icons/icons/Button Refresh-01.png
+
+ :/icons/icon-action-refresh:/icons/icon-action-refresh
- Refresh
+ &Refresh
Refresh the views
@@ -372,15 +350,15 @@
F5
-
- :/icons/icons/Save-01.png:/icons/icons/Save-01.png
+
+ :/icons/icon-action-commit:/icons/icon-action-commit
- Commit
+ &Commit
Commit modifications
@@ -390,12 +368,12 @@
Ctrl+M
-
- :/icons/icons/Document Copy-01.png:/icons/icons/Document Copy-01.png
+
+ :/icons/icon-item-diff:/icons/icon-item-diff
Diff
@@ -408,12 +386,12 @@
Ctrl+D
-
- :/icons/icons/File New-01.png:/icons/icons/File New-01.png
+
+ :/icons/icon-item-add:/icons/icon-item-add
Add
@@ -426,12 +404,12 @@
Ctrl++
-
- :/icons/icons/File Delete-01.png:/icons/icons/File Delete-01.png
+
+ :/icons/icon-item-delete:/icons/icon-item-delete
Delete
@@ -444,12 +422,12 @@
Ctrl+-
-
- :/icons/icons/Document Blank-01.png:/icons/icons/Document Blank-01.png
+
+ :/icons/icon-action-repo-new:/icons/icon-action-repo-new
&New...
@@ -462,12 +440,12 @@
Ctrl+N
-
- :/icons/icons/My Documents-01.png:/icons/icons/My Documents-01.png
+
+ :/icons/icon-action-repo-open:/icons/icon-action-repo-open
&Open...
@@ -494,27 +472,27 @@
Close the current workspace
-
- :/icons/icons/My Websites-01.png:/icons/icons/My Websites-01.png
+
+ :/icons/icon-action-repo-clone:/icons/icon-action-repo-clone
- Clone...
+ C&lone...
Clone a remote repository
-
- :/icons/icons/Button Upload-01.png:/icons/icons/Button Upload-01.png
+
+ :/icons/icon-action-push:/icons/icon-action-push
- Push
+ &Push
Push changes to the remote repository
@@ -524,15 +502,15 @@
Ctrl+P
-
- :/icons/icons/Button Download-01.png:/icons/icons/Button Download-01.png
+
+ :/icons/icon-action-pull:/icons/icon-action-pull
- Pull
+ Pu&ll
Pull changes from the remote repository
@@ -542,12 +520,12 @@
Ctrl+L
-
- :/icons/icons/File Open-01.png:/icons/icons/File Open-01.png
+
+ :/icons/icon-item-rename:/icons/icon-item-rename
Rename
@@ -560,12 +538,12 @@
Ctrl+R
-
- :/icons/icons/Button Turn Off-01.png:/icons/icons/Button Turn Off-01.png
+
+ :/icons/icon-action-quit:/icons/icon-action-quit
&Quit
@@ -581,12 +559,12 @@
true
-
- :/icons/icons/File History-01.png:/icons/icons/File History-01.png
+
+ :/icons/icon-item-history:/icons/icon-item-history
History
@@ -602,12 +580,12 @@
true
-
- :/icons/icons/Network MAC-01.png:/icons/icons/Network MAC-01.png
+
+ :/icons/icon-webview:/icons/icon-webview
Fossil UI
@@ -617,12 +595,12 @@
Starts the Fossil UI in the Web Browser
-
- :/icons/icons/Document-Revert-icon.png:/icons/icons/Document-Revert-icon.png
+
+ :/icons/icon-item-revert:/icons/icon-item-revert
Revert
@@ -632,12 +610,12 @@
Revert files to the last commited version
-
- :/icons/icons/Text Edit.png:/icons/icons/Text Edit.png
+
+ :/icons/icon-clear-log:/icons/icon-clear-log
Clear Log
@@ -647,12 +625,12 @@
Ctrl+K
-
- :/icons/icons/Clock-01.png:/icons/icons/Clock-01.png
+
+ :/icons/icon-action-timeline:/icons/icon-action-timeline
Timeline
@@ -662,12 +640,12 @@
Display the change history of the Fossil repository
-
- :/icons/icons/Document-01.png:/icons/icons/Document-01.png
+
+ :/icons/icon-item-file:/icons/icon-item-file
Open File
@@ -680,12 +658,12 @@
Ctrl+Return
-
- :/icons/icons/Folder-01.png:/icons/icons/Folder-01.png
+
+ :/icons/icon-action-folder-explore:/icons/icon-action-folder-explore
Open Containing
@@ -698,15 +676,15 @@
Alt+Return
-
- :/icons/icons/Button Reload-01.png:/icons/icons/Button Reload-01.png
+
+ :/icons/icon-action-undo:/icons/icon-action-undo
- Undo
+ U&ndo
Undo the last Fossil action
@@ -716,12 +694,12 @@
Ctrl+Z
-
- :/icons/icons/Battery-01.png:/icons/icons/Battery-01.png
+
+ :/icons/icon-application:/icons/icon-application
&About...
@@ -731,18 +709,18 @@
QAction::AboutRole
-
- :/icons/icons/Button Play-01.png:/icons/icons/Button Play-01.png
+
+ :/icons/icon-action-update:/icons/icon-action-update
- Update
+ &Update
- Update the workspace to the latest version
+ Update the workspace to a revision
Update the workspace to the latest version
@@ -749,12 +727,12 @@
Ctrl+U
-
- :/icons/icons/Gear-01.png:/icons/icons/Gear-01.png
+
+ :/icons/icon-action-settings:/icons/icon-action-settings
&Preferences...
@@ -837,12 +815,12 @@
View the workspace as a list of files
-
- :/icons/icons/Folder-01.png:/icons/icons/Folder-01.png
+
+ :/icons/icon-item-folder:/icons/icon-item-folder
Open Folder
@@ -852,12 +830,12 @@
Open the selected folder
-
- :/icons/icons/Folder Open-01.png:/icons/icons/Folder Open-01.png
+
+ :/icons/icon-action-folder-rename:/icons/icon-action-folder-rename
Rename Folder
@@ -865,26 +843,26 @@
Rename the selected folder
-
+
-
- :/icons/icons/Folder Add-01.png:/icons/icons/Folder Add-01.png
+
+ :/icons/icon-action-stash-new:/icons/icon-action-stash-new
- Stash changes
+ &Stash Changes
Stash changes
-
- :/icons/icons/Folder Open-01.png:/icons/icons/Folder Open-01.png
+
+ :/icons/icon-action-stash-apply:/icons/icon-action-stash-apply
Apply Stash
@@ -892,44 +870,115 @@
Apply stashed changes
-
-
- true
-
-
- &Stashed Changes
-
-
- View Stashed Changes
-
-
- View Stashed Changes
-
-
- Show the list of stashed changes
-
-
-
- :/icons/icons/Folder Delete-01.png:/icons/icons/Folder Delete-01.png
+
+ :/icons/icon-action-stash-delete:/icons/icon-action-stash-delete
Delete Stash
-
- :/icons/icons/Folder Explorer-01.png:/icons/icons/Folder Explorer-01.png
+
+ :/icons/icon-action-stash-diff:/icons/icon-action-stash-diff
Diff Stash
+
+
+
+
+ :/icons/icon-action-tag-new:/icons/icon-action-tag-new
+
+
+ Create &Tag
+
+
+ Create a tag for a revision
+
+
+ Create a tag for a revision
+
+
+
+
+
+ :/icons/icon-action-tag-delete:/icons/icon-action-tag-delete
+
+
+ Delete Tag
+
+
+ Delete Tag
+
+
+
+
+
+ :/icons/icon-item-branch:/icons/icon-item-branch
+
+
+ Create &Branch
+
+
+ Create a branch from a revision
+
+
+ Create a branch from a revision
+
+
+
+
+
+ :/icons/icon-action-merge:/icons/icon-action-merge
+
+
+ Merge Branch
+
+
+ Merge with a branch
+
+
+ Merge with a branch
+
+
+
+
+ true
+
+
+ Files and F&olders
+
+
+ View files and folders
+
+
+ View the workspace as files and folders
+
+
+
+
+ &All
+
+
+ Show all files
+
+
+
+
+
+ :/icons/icon-action-settings:/icons/icon-action-settings
+
+
+ F&ossil Settings
+
@@ -942,8 +991,10 @@
QWidget
1
-
+
+
+
ADDED ui/RevisionDialog.ui
Index: ui/RevisionDialog.ui
==================================================================
--- /dev/null
+++ ui/RevisionDialog.ui
@@ -0,0 +1,129 @@
+
+
+ RevisionDialog
+
+
+ Qt::WindowModal
+
+
+
+ 0
+ 0
+ 478
+ 177
+
+
+
+
+ 400
+ 0
+
+
+
+ true
+
+
+ -
+
+
-
+
+
+ Revision
+
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ Name
+
+
+
+ -
+
+
+ -
+
+
+ Integrate
+
+
+
+ -
+
+
+ Force
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ RevisionDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ RevisionDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
Index: ui/SettingsDialog.ui
==================================================================
--- ui/SettingsDialog.ui
+++ ui/SettingsDialog.ui
@@ -8,400 +8,181 @@
0
0
457
- 352
+ 204
Settings
+
+
+ :/icons/icon-application:/icons/icon-application
+
true
-
-
-
- 0
-
-
-
-
- :/icons/icons/Battery-01.png:/icons/icons/Battery-01.png
-
-
- Application
-
-
-
-
-
-
-
- 100
- 0
-
-
-
- Fossil Path
-
-
-
- -
-
-
-
-
-
- Path to the Fossil executable. Leave blank to use the default Fossil
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 24
- 24
-
-
-
- ...
-
-
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
- Graphical Diff
-
-
-
- -
-
-
-
-
-
- Path to graphical diff tool
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 24
- 24
-
-
-
- ...
-
-
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
- Graphical Merge
-
-
-
- -
-
-
-
-
-
- Path to the graphical merge tool
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 24
- 24
-
-
-
- ...
-
-
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
- HTTP Proxy
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- The URL of the HTTP proxy
-
-
-
- -
-
-
- HTTP Port
-
-
-
- -
-
-
- HTTP port to use for the Fossil web interface
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
- Commit Messages
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Clear the commit message history
-
-
- Clear
-
-
-
- -
-
-
- Web Browser
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Web browser to use for the Fossil web interface
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
- Double-click Action
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Action to perfom when double-clicking a file
-
-
- -1
-
-
-
- -
-
-
- Language
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Language for the user interface
-
-
-
-
-
-
-
-
- :/icons/icons/Book-01.png:/icons/icons/Book-01.png
-
-
- Repository
-
-
-
- QFormLayout::ExpandingFieldsGrow
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
- -
-
-
-
- 100
- 0
-
-
-
- Remote Url
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- The remote url used to push/pull changes.
-URL style user names and passwords are also supported.
-For example http://username:password@server.com/fossil
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
- Ignore List
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- A comma separated list of glob-style file/path patterns ignored in Fossil file operations
-
-
-
- -
-
-
-
- 100
- 0
-
-
-
- Ignore CR/NL
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- A comma separated list of glob-style file patterns to exclude from Fossil's CR/NL consistency checking
-
-
-
-
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ Fossil Path
+
+
+
+ -
+
+
-
+
+
+ Path to the Fossil executable. Leave blank to use the default Fossil
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 24
+ 24
+
+
+
+ ...
+
+
+
+
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ Commit Messages
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Clear the commit message history
+
+
+ Clear
+
+
+
+ -
+
+
+ Web Browser
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Web browser to use for the Fossil web interface
+
+
+
+ -
+
+
+
+ 100
+ 0
+
+
+
+ Double-click Action
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Action to perfom when double-clicking a file
+
+
+ -1
+
+
+
+ -
+
+
+ Language
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Language for the user interface
+
+
+
+
-