Fuel

Diff
Login

Differences From Artifact [f04effe7db]:

To Artifact [8b6494e94c]:


81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107


108
109
110
111
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105


106
107
108
109
110
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142







-
+

















-
-
+
+











-
+















-
+







{
	ui->setupUi(this);

	QAction *separator = new QAction(this);
	separator->setSeparator(true);

	// TableView
	ui->tableView->setModel(&getRepo().getFileModel());
	ui->tableView->setModel(&getWorkspace().getFileModel());

	ui->tableView->addAction(ui->actionDiff);
	ui->tableView->addAction(ui->actionHistory);
	ui->tableView->addAction(ui->actionOpenFile);
	ui->tableView->addAction(ui->actionOpenContaining);
	ui->tableView->addAction(separator);
	ui->tableView->addAction(ui->actionAdd);
	ui->tableView->addAction(ui->actionRevert);
	ui->tableView->addAction(ui->actionRename);
	ui->tableView->addAction(ui->actionDelete);
	connect( ui->tableView,
		SIGNAL( dragOutEvent() ),
		SLOT( onFileViewDragOut() ),
		Qt::DirectConnection );

	QStringList header;
	header << tr("Status") << tr("File") << tr("Extension") << tr("Modified") << tr("Path");
	getRepo().getFileModel().setHorizontalHeaderLabels(header);
	getRepo().getFileModel().horizontalHeaderItem(COLUMN_STATUS)->setTextAlignment(Qt::AlignCenter);
	getWorkspace().getFileModel().setHorizontalHeaderLabels(header);
	getWorkspace().getFileModel().horizontalHeaderItem(COLUMN_STATUS)->setTextAlignment(Qt::AlignCenter);

	// Needed on OSX as the preset value from the GUI editor is not always reflected
	ui->tableView->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
	ui->tableView->horizontalHeader()->setMovable(true);
#else
	ui->tableView->horizontalHeader()->setSectionsMovable(true);
#endif
	ui->tableView->horizontalHeader()->setStretchLastSection(true);

	// TreeView
	ui->treeView->setModel(&getRepo().getDirModel());
	ui->treeView->setModel(&getWorkspace().getDirModel());
	connect( ui->treeView->selectionModel(),
		SIGNAL( selectionChanged(const QItemSelection &, const QItemSelection &) ),
		SLOT( onTreeViewSelectionChanged(const QItemSelection &, const QItemSelection &) ),
		Qt::DirectConnection );

	ui->treeView->addAction(ui->actionCommit);
	ui->treeView->addAction(ui->actionOpenFolder);
	ui->treeView->addAction(ui->actionAdd);
	ui->treeView->addAction(ui->actionRevert);
	ui->treeView->addAction(ui->actionDelete);
	ui->treeView->addAction(separator);
	ui->treeView->addAction(ui->actionRenameFolder);
	ui->treeView->addAction(ui->actionOpenFolder);

	// StashView
	ui->tableViewStash->setModel(&getRepo().getStashModel());
	ui->tableViewStash->setModel(&getWorkspace().getStashModel());
	ui->tableViewStash->addAction(ui->actionApplyStash);
	ui->tableViewStash->addAction(ui->actionDiffStash);
	ui->tableViewStash->addAction(ui->actionDeleteStash);
	ui->tableViewStash->horizontalHeader()->setSortIndicatorShown(false);

	// Recent Workspaces
	// Locate a sequence of two separator actions in file menu
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220







-
+







//------------------------------------------------------------------------------
MainWindow::~MainWindow()
{
	stopUI();
	updateSettings();

	// Dispose RepoFiles
	for(Workspace::filemap_t::iterator it = getRepo().getFiles().begin(); it!=getRepo().getFiles().end(); ++it)
	for(Workspace::filemap_t::iterator it = getWorkspace().getFiles().begin(); it!=getWorkspace().getFiles().end(); ++it)
		delete *it;

	delete ui;
}
//-----------------------------------------------------------------------------
const QString &MainWindow::getCurrentWorkspace()
{
552
553
554
555
556
557
558
559
560


561
562
563
564
565
566
567
568
569


570
571
572
573
574
575
576
552
553
554
555
556
557
558


559
560
561
562
563
564
565
566
567


568
569
570
571
572
573
574
575
576







-
-
+
+







-
-
+
+







	// Load repository info
	RepoStatus st = fossil().getRepoStatus();

	if(st==REPO_NOT_FOUND)
	{
		setStatus(tr("No workspace detected."));
		enableActions(false);
		getRepo().getFileModel().removeRows(0, getRepo().getFileModel().rowCount());
		getRepo().getDirModel().clear();
		getWorkspace().getFileModel().removeRows(0, getWorkspace().getFileModel().rowCount());
		getWorkspace().getDirModel().clear();
		setWindowTitle(title);
		return false;
	}
	else if(st==REPO_OLD_SCHEMA)
	{
		setStatus(tr("Old repository schema detected. Consider running 'fossil rebuild'"));
		enableActions(false);
		getRepo().getFileModel().removeRows(0, getRepo().getFileModel().rowCount());
		getRepo().getDirModel().clear();
		getWorkspace().getFileModel().removeRows(0, getWorkspace().getFileModel().rowCount());
		getWorkspace().getDirModel().clear();
		setWindowTitle(title);
		return true;
	}

	loadFossilSettings();
	scanWorkspace();
	setStatus("");
720
721
722
723
724
725
726
727

728
729
730
731
732
733
734
720
721
722
723
724
725
726

727
728
729
730
731
732
733
734







-
+







	uiCallback.endProcess();
}

//------------------------------------------------------------------------------
void MainWindow::scanWorkspace()
{
	setBusy(true);
	getRepo().scanWorkspace(ui->actionViewUnknown->isChecked(),
	getWorkspace().scanWorkspace(ui->actionViewUnknown->isChecked(),
							ui->actionViewIgnored->isChecked(),
							ui->actionViewModified->isChecked(),
							ui->actionViewUnchanged->isChecked(),
							settings.GetFossilValue(FOSSIL_SETTING_IGNORE_GLOB).toString(),
							uiCallback,
							operationAborted
							);
776
777
778
779
780
781
782
783

784
785
786
787

788
789
790
791
792
793
794


795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810

811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829

830
831
832
833
834
835
836
776
777
778
779
780
781
782

783
784
785
786

787
788
789
790
791
792


793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809

810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828

829
830
831
832
833
834
835
836







-
+



-
+





-
-
+
+















-
+


















-
+







	}
}

//------------------------------------------------------------------------------
void MainWindow::updateDirView()
{
	// Directory View
	getRepo().getDirModel().clear();
	getWorkspace().getDirModel().clear();

	QStringList header;
	header << tr("Folders");
	getRepo().getDirModel().setHorizontalHeaderLabels(header);
	getWorkspace().getDirModel().setHorizontalHeaderLabels(header);

	QStandardItem *root = new QStandardItem(QIcon(":icons/icons/My Documents-01.png"), fossil().getProjectName());
	root->setData(""); // Empty Path
	root->setEditable(false);

	getRepo().getDirModel().appendRow(root);
	for(stringset_t::iterator it = getRepo().getPaths().begin(); it!=getRepo().getPaths().end(); ++it)
	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->treeView->expandToDepth(0);
	ui->treeView->sortByColumn(0, Qt::AscendingOrder);
}

//------------------------------------------------------------------------------
void MainWindow::updateFileView()
{
	// Clear content except headers
	getRepo().getFileModel().removeRows(0, getRepo().getFileModel().rowCount());
	getWorkspace().getFileModel().removeRows(0, getWorkspace().getFileModel().rowCount());

	struct { RepoFile::EntryType type; QString text; const char *icon; }
	stats[] =
	{
		{   RepoFile::TYPE_EDITTED, tr("Edited"), ":icons/icons/Button Blank Yellow-01.png" },
		{   RepoFile::TYPE_UNCHANGED, tr("Unchanged"), ":icons/icons/Button Blank Green-01.png" },
		{   RepoFile::TYPE_ADDED, tr("Added"), ":icons/icons/Button Add-01.png" },
		{   RepoFile::TYPE_DELETED, tr("Deleted"), ":icons/icons/Button Close-01.png" },
		{   RepoFile::TYPE_RENAMED, tr("Renamed"), ":icons/icons/Button Reload-01.png" },
		{   RepoFile::TYPE_MISSING, tr("Missing"), ":icons/icons/Button Help-01.png" },
		{   RepoFile::TYPE_CONFLICTED, tr("Conflicted"), ":icons/icons/Button Blank Red-01.png" },
	};

	QFileIconProvider icon_provider;

	bool display_path = viewMode==VIEWMODE_LIST || selectedDirs.count() > 1;

	size_t item_id=0;
	for(Workspace::filemap_t::iterator it = getRepo().getFiles().begin(); it!=getRepo().getFiles().end(); ++it)
	for(Workspace::filemap_t::iterator it = getWorkspace().getFiles().begin(); it!=getWorkspace().getFiles().end(); ++it)
	{
		const RepoFile &e = *it.value();
		QString path = e.getPath();

		// In Tree mode, filter all items not included in the current dir
		if(viewMode==VIEWMODE_TREE && !selectedDirs.contains(path))
			continue;
847
848
849
850
851
852
853
854

855
856
857
858
859
860

861
862
863
864
865
866
867
868
869
870

871
872
873


874
875
876
877
878
879
880
881
882
883
884

885
886
887
888

889
890

891
892
893
894

895
896
897
898
899
900
901
847
848
849
850
851
852
853

854
855
856
857
858
859

860
861
862
863
864
865
866
867
868
869

870
871


872
873
874
875
876
877
878
879
880
881
882
883

884
885
886
887

888
889

890
891
892
893

894
895
896
897
898
899
900
901







-
+





-
+









-
+

-
-
+
+










-
+



-
+

-
+



-
+







				status_icon_path = stats[t].icon;
				break;
			}
		}

		QStandardItem *status = new QStandardItem(QIcon(status_icon_path), status_text);
		status->setToolTip(status_text);
		getRepo().getFileModel().setItem(item_id, COLUMN_STATUS, status);
		getWorkspace().getFileModel().setItem(item_id, COLUMN_STATUS, status);

		QFileInfo finfo = e.getFileInfo();
		QIcon icon = icon_provider.icon(finfo);

		QStandardItem *filename_item = 0;
		getRepo().getFileModel().setItem(item_id, COLUMN_PATH, new QStandardItem(path));
		getWorkspace().getFileModel().setItem(item_id, COLUMN_PATH, new QStandardItem(path));

		if(display_path)
			filename_item = new QStandardItem(icon, QDir::toNativeSeparators(e.getFilePath()));
		else
			filename_item = new QStandardItem(icon, e.getFilename());

		Q_ASSERT(filename_item);
		// Keep the path in the user data
		filename_item->setData(e.getFilePath());
		getRepo().getFileModel().setItem(item_id, COLUMN_FILENAME, filename_item);
		getWorkspace().getFileModel().setItem(item_id, COLUMN_FILENAME, filename_item);

		getRepo().getFileModel().setItem(item_id, COLUMN_EXTENSION, new QStandardItem(finfo.suffix()));
		getRepo().getFileModel().setItem(item_id, COLUMN_MODIFIED, new QStandardItem(finfo.lastModified().toString(Qt::SystemLocaleShortDate)));
		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)));

		++item_id;
	}

	ui->tableView->resizeRowsToContents();
}

//------------------------------------------------------------------------------
void MainWindow::updateStashView()
{
	getRepo().getStashModel().clear();
	getWorkspace().getStashModel().clear();

	QStringList header;
	header << tr("Stashes");
	getRepo().getStashModel().setHorizontalHeaderLabels(header);
	getWorkspace().getStashModel().setHorizontalHeaderLabels(header);

	for(stashmap_t::iterator it=getRepo().getStashes().begin(); it!=getRepo().getStashes().end(); ++it)
	for(stashmap_t::iterator it=getWorkspace().getStashes().begin(); it!=getWorkspace().getStashes().end(); ++it)
	{
		QStandardItem *item = new QStandardItem(it.key());
		item->setToolTip(it.key());
		getRepo().getStashModel().appendRow(item);
		getWorkspace().getStashModel().appendRow(item);
	}
	ui->tableViewStash->resizeColumnsToContents();
	ui->tableViewStash->resizeRowsToContents();
}

//------------------------------------------------------------------------------
void MainWindow::log(const QString &text, bool isHTML)
941
942
943
944
945
946
947
948

949
950
951
952
953
954
955
941
942
943
944
945
946
947

948
949
950
951
952
953
954
955







-
+








		if(store->contains("Active") && store->value("Active").toBool())
			setCurrentWorkspace(wk);
	}
	store->endArray();

	store->beginReadArray("FileColumns");
	for(int i=0; i<getRepo().getFileModel().columnCount(); ++i)
	for(int i=0; i<getWorkspace().getFileModel().columnCount(); ++i)
	{
		store->setArrayIndex(i);
		if(store->contains("Width"))
		{
			int width = store->value("Width").toInt();
			ui->tableView->setColumnWidth(i, width);
		}
1015
1016
1017
1018
1019
1020
1021
1022
1023


1024
1025
1026
1027
1028
1029
1030
1015
1016
1017
1018
1019
1020
1021


1022
1023
1024
1025
1026
1027
1028
1029
1030







-
-
+
+







		if(getCurrentWorkspace() == workspaceHistory[i])
			store->setValue("Active", true);
		else
			store->remove("Active");
	}
	store->endArray();

	store->beginWriteArray("FileColumns", getRepo().getFileModel().columnCount());
	for(int i=0; i<getRepo().getFileModel().columnCount(); ++i)
	store->beginWriteArray("FileColumns", getWorkspace().getFileModel().columnCount());
	for(int i=0; i<getWorkspace().getFileModel().columnCount(); ++i)
	{
		store->setArrayIndex(i);
		store->setValue("Width", ui->tableView->columnWidth(i));
		int index = ui->tableView->horizontalHeader()->visualIndex(i);
		store->setValue("Index", index);
	}
	store->endArray();
1082
1083
1084
1085
1086
1087
1088
1089

1090
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
1082
1083
1084
1085
1086
1087
1088

1089
1090
1091
1092
1093
1094
1095
1096

1097
1098
1099
1100
1101
1102
1103
1104







-
+







-
+







void MainWindow::getSelectionPaths(stringset_t &paths)
{
	// Determine the directories selected
	QModelIndexList selection = ui->treeView->selectionModel()->selectedIndexes();
	for(QModelIndexList::iterator mi_it = selection.begin(); mi_it!=selection.end(); ++mi_it)
	{
		const QModelIndex &mi = *mi_it;
		QVariant data = getRepo().getDirModel().data(mi, REPODIRMODEL_ROLE_PATH);
		QVariant data = getWorkspace().getDirModel().data(mi, REPODIRMODEL_ROLE_PATH);
		paths.insert(data.toString());
	}
}
//------------------------------------------------------------------------------
// Select all workspace files that match the includeMask
void MainWindow::getAllFilenames(QStringList &filenames, int includeMask)
{
	for(Workspace::filemap_t::iterator it=getRepo().getFiles().begin(); it!=getRepo().getFiles().end(); ++it)
	for(Workspace::filemap_t::iterator it=getWorkspace().getFiles().begin(); it!=getWorkspace().getFiles().end(); ++it)
	{
		const RepoFile &e = *(*it);

		// Skip unwanted file types
		if(!(includeMask & e.getType()))
			continue;

1114
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128







-
+







	QModelIndexList selection = ui->treeView->selectionModel()->selectedIndexes();
	if(!(selection.empty() && allIfEmpty))
	{
		getSelectionPaths(paths);
	}

	// Select the actual files form the selected directories
	for(Workspace::filemap_t::iterator it=getRepo().getFiles().begin(); it!=getRepo().getFiles().end(); ++it)
	for(Workspace::filemap_t::iterator it=getWorkspace().getFiles().begin(); it!=getWorkspace().getFiles().end(); ++it)
	{
		const RepoFile &e = *(*it);

		// Skip unwanted file types
		if(!(includeMask & e.getType()))
			continue;

1168
1169
1170
1171
1172
1173
1174
1175

1176
1177
1178


1179
1180
1181
1182
1183
1184
1185
1168
1169
1170
1171
1172
1173
1174

1175
1176


1177
1178
1179
1180
1181
1182
1183
1184
1185







-
+

-
-
+
+







		const QModelIndex &mi = *mi_it;

		// FIXME: we are being called once per cell of each row
		// but we only need column 1. There must be a better way
		if(mi.column()!=COLUMN_FILENAME)
			continue;

		QVariant data = getRepo().getFileModel().data(mi, Qt::UserRole+1);
		QVariant data = getWorkspace().getFileModel().data(mi, Qt::UserRole+1);
		QString filename = data.toString();
		Workspace::filemap_t::iterator e_it = getRepo().getFiles().find(filename);
		Q_ASSERT(e_it!=getRepo().getFiles().end());
		Workspace::filemap_t::iterator e_it = getWorkspace().getFiles().find(filename);
		Q_ASSERT(e_it!=getWorkspace().getFiles().end());
		const RepoFile &e = *e_it.value();

		// Skip unwanted files
		if(!(includeMask & e.getType()))
			continue;

		filenames.append(filename);
1198
1199
1200
1201
1202
1203
1204
1205

1206
1207
1208
1209
1210
1211
1212
1198
1199
1200
1201
1202
1203
1204

1205
1206
1207
1208
1209
1210
1211
1212







-
+








	for(QModelIndexList::iterator mi_it = selection.begin(); mi_it!=selection.end(); ++mi_it)
	{
		const QModelIndex &mi = *mi_it;

		if(mi.column()!=0)
			continue;
		QString name = getRepo().getStashModel().data(mi).toString();
		QString name = getWorkspace().getStashModel().data(mi).toString();
		stashNames.append(name);
	}
}

//------------------------------------------------------------------------------
bool MainWindow::diffFile(const QString &repoFile)
{
1702
1703
1704
1705
1706
1707
1708
1709

1710
1711
1712
1713
1714
1715
1716
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714
1715
1716







-
+







		return;

	selectedDirs.clear();

	for(int i=0; i<num_selected; ++i)
	{
		QModelIndex index = selection.at(i);
		QString dir = getRepo().getDirModel().data(index, REPODIRMODEL_ROLE_PATH).toString();
		QString dir = getWorkspace().getDirModel().data(index, REPODIRMODEL_ROLE_PATH).toString();
		selectedDirs.insert(dir);
	}

	updateFileView();
}

//------------------------------------------------------------------------------
1724
1725
1726
1727
1728
1729
1730
1731

1732
1733
1734
1735
1736
1737
1738
1724
1725
1726
1727
1728
1729
1730

1731
1732
1733
1734
1735
1736
1737
1738







-
+







	QModelIndex index = selection.indexes().at(0);
	on_treeView_doubleClicked(index);
}

//------------------------------------------------------------------------------
void MainWindow::on_treeView_doubleClicked(const QModelIndex &index)
{
	QString target = getRepo().getDirModel().data(index, REPODIRMODEL_ROLE_PATH).toString();
	QString target = getWorkspace().getDirModel().data(index, REPODIRMODEL_ROLE_PATH).toString();
	target = getCurrentWorkspace() + PATH_SEPARATOR + target;

	QUrl url = QUrl::fromLocalFile(target);
	QDesktopServices::openUrl(url);
}

//------------------------------------------------------------------------------
1778
1779
1780
1781
1782
1783
1784
1785

1786
1787
1788
1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802
1778
1779
1780
1781
1782
1783
1784

1785
1786
1787
1788
1789
1790
1791
1792
1793
1794

1795
1796
1797
1798
1799
1800
1801
1802







-
+









-
+







			QMessageBox::critical(this, tr("Error"), tr("Cannot rename folder.")+"\n" +tr("Folder name contains invalid characters."));
			return;
		}
	}

	QString new_path = old_path.left(dir_start) + new_name;

	if(getRepo().getPaths().contains(new_path))
	if(getWorkspace().getPaths().contains(new_path))
	{
		QMessageBox::critical(this, tr("Error"), tr("Cannot rename folder.")+"\n" +tr("This folder exists already."));
		return;
	}

	// Collect the files to be moved
	Workspace::filelist_t files_to_move;
	QStringList new_paths;
	QStringList operations;
	foreach(RepoFile *r, getRepo().getFiles())
	foreach(RepoFile *r, getWorkspace().getFiles())
	{
		if(r->getPath().indexOf(old_path)!=0)
			continue;

		files_to_move.append(r);
		QString new_dir = new_path + r->getPath().mid(old_path.length());
		new_paths.append(new_dir);
1931
1932
1933
1934
1935
1936
1937
1938

1939
1940
1941
1942
1943
1944
1945
1931
1932
1933
1934
1935
1936
1937

1938
1939
1940
1941
1942
1943
1944
1945







-
+







	if(stash_name.indexOf("\"")!=-1 || stash_name.isEmpty())
	{
		QMessageBox::critical(this, tr("Error"), tr("Invalid stash name"));
		return;
	}

	// Check that this stash does not exist
	for(stashmap_t::iterator it=getRepo().getStashes().begin(); it!=getRepo().getStashes().end(); ++it)
	for(stashmap_t::iterator it=getWorkspace().getStashes().begin(); it!=getWorkspace().getStashes().end(); ++it)
	{
		if(stash_name == it.key())
		{
			QMessageBox::critical(this, tr("Error"), tr("This stash already exists"));
			return;
		}
	}
1959
1960
1961
1962
1963
1964
1965
1966
1967


1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980


1981
1982
1983
1984
1985
1986
1987
1959
1960
1961
1962
1963
1964
1965


1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978


1979
1980
1981
1982
1983
1984
1985
1986
1987







-
-
+
+











-
-
+
+







	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;

	// Apply stashes
	for(QStringList::iterator it=stashes.begin(); it!=stashes.end(); ++it)
	{
		stashmap_t::iterator id_it = getRepo().getStashes().find(*it);
		Q_ASSERT(id_it!=getRepo().getStashes().end());
		stashmap_t::iterator id_it = getWorkspace().getStashes().find(*it);
		Q_ASSERT(id_it!=getWorkspace().getStashes().end());

		if(!fossil().stashApply(*id_it))
		{
			log(tr("Stash application aborted due to errors")+"\n");
			return;
		}
	}

	// Delete stashes
	for(QStringList::iterator it=stashes.begin(); delete_stashes && it!=stashes.end(); ++it)
	{
		stashmap_t::iterator id_it = getRepo().getStashes().find(*it);
		Q_ASSERT(id_it!=getRepo().getStashes().end());
		stashmap_t::iterator id_it = getWorkspace().getStashes().find(*it);
		Q_ASSERT(id_it!=getWorkspace().getStashes().end());

		if(!fossil().stashDrop(*id_it))
		{
			log(tr("Stash deletion aborted due to errors")+"\n");
			return;
		}
	}
2000
2001
2002
2003
2004
2005
2006
2007
2008


2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030


2031
2032
2033
2034
2035
2036
2037
2000
2001
2002
2003
2004
2005
2006


2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028


2029
2030
2031
2032
2033
2034
2035
2036
2037







-
-
+
+




















-
-
+
+








	if(!FileActionDialog::run(this, tr("Delete Stashes"), tr("The following stashes will be deleted.")+"\n"+tr("Are you sure?"), stashes))
		return;

	// Delete stashes
	for(QStringList::iterator it=stashes.begin(); it!=stashes.end(); ++it)
	{
		stashmap_t::iterator id_it = getRepo().getStashes().find(*it);
		Q_ASSERT(id_it!=getRepo().getStashes().end());
		stashmap_t::iterator id_it = getWorkspace().getStashes().find(*it);
		Q_ASSERT(id_it!=getWorkspace().getStashes().end());

		if(!fossil().stashDrop(*id_it))
		{
			log(tr("Stash deletion aborted due to errors")+"\n");
			return;
		}
	}

	refresh();
}

//------------------------------------------------------------------------------
void MainWindow::on_actionDiffStash_triggered()
{
	QStringList stashes;
	getStashViewSelection(stashes);

	if(stashes.length() != 1)
		return;

	stashmap_t::iterator id_it = getRepo().getStashes().find(*stashes.begin());
	Q_ASSERT(id_it!=getRepo().getStashes().end());
	stashmap_t::iterator id_it = getWorkspace().getStashes().find(*stashes.begin());
	Q_ASSERT(id_it!=getWorkspace().getStashes().end());

	// Run diff
	fossil().stashDiff(*id_it);
}

//------------------------------------------------------------------------------
void MainWindow::onFileViewDragOut()