Fuel

Diff
Login

Differences From Artifact [f87fb7425a]:

To Artifact [b73396d7d6]:


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(&repoFileModel);
	ui->tableView->setModel(&getRepo().repoFileModel);

	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");
	repoFileModel.setHorizontalHeaderLabels(header);
	repoFileModel.horizontalHeaderItem(COLUMN_STATUS)->setTextAlignment(Qt::AlignCenter);
	getRepo().repoFileModel.setHorizontalHeaderLabels(header);
	getRepo().repoFileModel.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(&repoDirModel);
	ui->treeView->setModel(&getRepo().repoDirModel);
	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(&repoStashModel);
	ui->tableViewStash->setModel(&getRepo().repoStashModel);
	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(filemap_t::iterator it = workspaceFiles.begin(); it!=workspaceFiles.end(); ++it)
	for(Repository::filemap_t::iterator it = getRepo().workspaceFiles.begin(); it!=getRepo().workspaceFiles.end(); ++it)
		delete *it;

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


562
563
564
565
566
567
568
569
570


571
572
573
574
575
576
577
553
554
555
556
557
558
559


560
561
562
563
564
565
566
567
568


569
570
571
572
573
574
575
576
577







-
-
+
+







-
-
+
+







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

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

	loadFossilSettings();
	scanWorkspace();
	setStatus("");
602
603
604
605
606
607
608
609

610
611
612
613


614
615
616
617
618
619
620
602
603
604
605
606
607
608

609
610
611


612
613
614
615
616
617
618
619
620







-
+


-
-
+
+







	bool scan_files = ui->actionViewUnknown->isChecked();

	setStatus(tr("Scanning Workspace..."));
	setBusy(true);
	QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

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

	workspaceFiles.clear();
	pathSet.clear();
	getRepo().workspaceFiles.clear();
	getRepo().pathSet.clear();

	operationAborted = false;

	if(scan_files)
	{
		QCoreApplication::processEvents();

635
636
637
638
639
640
641
642
643


644
645
646
647
648
649
650
635
636
637
638
639
640
641


642
643
644
645
646
647
648
649
650







-
-
+
+







			QString fullpath = it->absoluteFilePath();

			// Skip fossil files
			if(filename == FOSSIL_CHECKOUT1 || filename == FOSSIL_CHECKOUT2 || (!bridge.getRepositoryFile().isEmpty() && QFileInfo(fullpath) == QFileInfo(bridge.getRepositoryFile())))
				continue;

			RepoFile *rf = new RepoFile(*it, RepoFile::TYPE_UNKNOWN, wkdir);
			workspaceFiles.insert(rf->getFilePath(), rf);
			pathSet.insert(rf->getPath());
			getRepo().workspaceFiles.insert(rf->getFilePath(), rf);
			getRepo().pathSet.insert(rf->getPath());
		}
	}

	setStatus(tr("Updating..."));
	QCoreApplication::processEvents();

	// Update Files and Directories
684
685
686
687
688
689
690
691

692
693
694
695
696
697

698
699
700

701
702
703
704

705
706
707
708
709
710


711
712
713
714
715
716
717

718
719
720
721

722
723
724
725
726
727
728
684
685
686
687
688
689
690

691
692
693
694
695
696

697
698
699

700
701
702
703

704
705
706
707
708


709
710
711
712
713
714
715
716

717
718
719
720

721
722
723
724
725
726
727
728







-
+





-
+


-
+



-
+




-
-
+
+






-
+



-
+







		else if(status_text=="CONFLICT")
			type = RepoFile::TYPE_CONFLICTED;

		// Filter unwanted file types
		if( ((type & RepoFile::TYPE_MODIFIED) && !ui->actionViewModified->isChecked()) ||
			((type & RepoFile::TYPE_UNCHANGED) && !ui->actionViewUnchanged->isChecked() ))
		{
			workspaceFiles.remove(fname);
			getRepo().workspaceFiles.remove(fname);
			continue;
		}
		else
			add_missing = true;

		filemap_t::iterator it = workspaceFiles.find(fname);
		Repository::filemap_t::iterator it = getRepo().workspaceFiles.find(fname);

		RepoFile *rf = 0;
		if(add_missing && it==workspaceFiles.end())
		if(add_missing && it==getRepo().workspaceFiles.end())
		{
			QFileInfo info(wkdir+QDir::separator()+fname);
			rf = new RepoFile(info, type, wkdir);
			workspaceFiles.insert(rf->getFilePath(), rf);
			getRepo().workspaceFiles.insert(rf->getFilePath(), rf);
		}

		if(!rf)
		{
			it = workspaceFiles.find(fname);
			Q_ASSERT(it!=workspaceFiles.end());
			it = getRepo().workspaceFiles.find(fname);
			Q_ASSERT(it!=getRepo().workspaceFiles.end());
			rf = *it;
		}

		rf->setType(type);

		QString path = rf->getPath();
		pathSet.insert(path);
		getRepo().pathSet.insert(path);
	}

	// Load the stash
	bridge.stashList(stashMap);
	bridge.stashList(getRepo().stashMap);

	// Update the file item model
_done:
	updateDirView();
	updateFileView();
	updateStashView();

767
768
769
770
771
772
773
774

775
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
837
838
839
840
841
842
843
844
845

846
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
767
768
769
770
771
772
773

774
775
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
837
838
839
840
841
842
843
844

845
846
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







-
+



-
+





-
-
+
+















-
+















-
+


-
+





-
+


















-
+





-
+









-
+

-
-
+
+










-
+



-
+

-
+



-
+







	}
}

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

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

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

	repoDirModel.appendRow(root);
	for(stringset_t::iterator it = pathSet.begin(); it!=pathSet.end(); ++it)
	getRepo().repoDirModel.appendRow(root);
	for(stringset_t::iterator it = getRepo().pathSet.begin(); it!=getRepo().pathSet.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
	repoFileModel.removeRows(0, repoFileModel.rowCount());
	getRepo().repoFileModel.removeRows(0, getRepo().repoFileModel.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;
	bool display_path = viewMode==VIEWMODE_LIST || getRepo().selectedDirs.count() > 1;

	size_t item_id=0;
	for(filemap_t::iterator it = workspaceFiles.begin(); it!=workspaceFiles.end(); ++it)
	for(Repository::filemap_t::iterator it = getRepo().workspaceFiles.begin(); it!=getRepo().workspaceFiles.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))
		if(viewMode==VIEWMODE_TREE && !getRepo().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

		for(size_t t=0; t<COUNTOF(stats); ++t)
		{
			if(e.getType() == stats[t].type)
			{
				status_text = stats[t].text;
				status_icon_path = stats[t].icon;
				break;
			}
		}

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

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

		QStandardItem *filename_item = 0;
		repoFileModel.setItem(item_id, COLUMN_PATH, new QStandardItem(path));
		getRepo().repoFileModel.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());
		repoFileModel.setItem(item_id, COLUMN_FILENAME, filename_item);
		getRepo().repoFileModel.setItem(item_id, COLUMN_FILENAME, filename_item);

		repoFileModel.setItem(item_id, COLUMN_EXTENSION, new QStandardItem(finfo.suffix()));
		repoFileModel.setItem(item_id, COLUMN_MODIFIED, new QStandardItem(finfo.lastModified().toString(Qt::SystemLocaleShortDate)));
		getRepo().repoFileModel.setItem(item_id, COLUMN_EXTENSION, new QStandardItem(finfo.suffix()));
		getRepo().repoFileModel.setItem(item_id, COLUMN_MODIFIED, new QStandardItem(finfo.lastModified().toString(Qt::SystemLocaleShortDate)));

		++item_id;
	}

	ui->tableView->resizeRowsToContents();
}

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

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

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

//------------------------------------------------------------------------------
void MainWindow::log(const QString &text, bool isHTML)
932
933
934
935
936
937
938
939

940
941
942
943
944
945
946
932
933
934
935
936
937
938

939
940
941
942
943
944
945
946







-
+








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

	store->beginReadArray("FileColumns");
	for(int i=0; i<repoFileModel.columnCount(); ++i)
	for(int i=0; i<getRepo().repoFileModel.columnCount(); ++i)
	{
		store->setArrayIndex(i);
		if(store->contains("Width"))
		{
			int width = store->value("Width").toInt();
			ui->tableView->setColumnWidth(i, width);
		}
1006
1007
1008
1009
1010
1011
1012
1013
1014


1015
1016
1017
1018
1019
1020
1021
1006
1007
1008
1009
1010
1011
1012


1013
1014
1015
1016
1017
1018
1019
1020
1021







-
-
+
+







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

	store->beginWriteArray("FileColumns", repoFileModel.columnCount());
	for(int i=0; i<repoFileModel.columnCount(); ++i)
	store->beginWriteArray("FileColumns", getRepo().repoFileModel.columnCount());
	for(int i=0; i<getRepo().repoFileModel.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();
1073
1074
1075
1076
1077
1078
1079
1080

1081
1082
1083
1084
1085
1086
1087
1088

1089
1090
1091
1092
1093
1094
1095
1073
1074
1075
1076
1077
1078
1079

1080
1081
1082
1083
1084
1085
1086
1087

1088
1089
1090
1091
1092
1093
1094
1095







-
+







-
+







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 = repoDirModel.data(mi, REPODIRMODEL_ROLE_PATH);
		QVariant data = getRepo().repoDirModel.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(filemap_t::iterator it=workspaceFiles.begin(); it!=workspaceFiles.end(); ++it)
	for(Repository::filemap_t::iterator it=getRepo().workspaceFiles.begin(); it!=getRepo().workspaceFiles.end(); ++it)
	{
		const RepoFile &e = *(*it);

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

1105
1106
1107
1108
1109
1110
1111
1112

1113
1114
1115
1116
1117
1118
1119
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
1119







-
+







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

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

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

1159
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169


1170
1171
1172
1173
1174
1175
1176
1159
1160
1161
1162
1163
1164
1165

1166
1167


1168
1169
1170
1171
1172
1173
1174
1175
1176







-
+

-
-
+
+







		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 = repoFileModel.data(mi, Qt::UserRole+1);
		QVariant data = getRepo().repoFileModel.data(mi, Qt::UserRole+1);
		QString filename = data.toString();
		filemap_t::iterator e_it = workspaceFiles.find(filename);
		Q_ASSERT(e_it!=workspaceFiles.end());
		Repository::filemap_t::iterator e_it = getRepo().workspaceFiles.find(filename);
		Q_ASSERT(e_it!=getRepo().workspaceFiles.end());
		const RepoFile &e = *e_it.value();

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

		filenames.append(filename);
1189
1190
1191
1192
1193
1194
1195
1196

1197
1198
1199
1200
1201
1202
1203
1189
1190
1191
1192
1193
1194
1195

1196
1197
1198
1199
1200
1201
1202
1203







-
+








	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 = repoStashModel.data(mi).toString();
		QString name = getRepo().repoStashModel.data(mi).toString();
		stashNames.append(name);
	}
}

//------------------------------------------------------------------------------
bool MainWindow::diffFile(const QString &repoFile)
{
1688
1689
1690
1691
1692
1693
1694
1695

1696
1697
1698
1699
1700
1701


1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722

1723
1724
1725
1726
1727
1728
1729
1688
1689
1690
1691
1692
1693
1694

1695
1696
1697
1698
1699


1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721

1722
1723
1724
1725
1726
1727
1728
1729







-
+




-
-
+
+




















-
+







	QModelIndexList selection = ui->treeView->selectionModel()->selectedIndexes();
	int num_selected = selection.count();

	// Do not modify the selection if nothing is selected
	if(num_selected==0)
		return;

	selectedDirs.clear();
	getRepo().selectedDirs.clear();

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

	updateFileView();
}

//------------------------------------------------------------------------------
void MainWindow::on_actionOpenFolder_triggered()
{
	const QItemSelection &selection =  ui->treeView->selectionModel()->selection();

	if(selection.indexes().count()!=1)
		return;

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

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

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

//------------------------------------------------------------------------------
1769
1770
1771
1772
1773
1774
1775
1776

1777
1778
1779
1780
1781
1782
1783

1784
1785
1786

1787
1788
1789
1790
1791
1792
1793
1769
1770
1771
1772
1773
1774
1775

1776
1777
1778
1779
1780
1781
1782

1783
1784
1785

1786
1787
1788
1789
1790
1791
1792
1793







-
+






-
+


-
+







			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(pathSet.contains(new_path))
	if(getRepo().pathSet.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
	filelist_t files_to_move;
	Repository::filelist_t files_to_move;
	QStringList new_paths;
	QStringList operations;
	foreach(RepoFile *r, workspaceFiles)
	foreach(RepoFile *r, getRepo().workspaceFiles)
	{
		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);
1922
1923
1924
1925
1926
1927
1928
1929

1930
1931
1932
1933
1934
1935
1936
1922
1923
1924
1925
1926
1927
1928

1929
1930
1931
1932
1933
1934
1935
1936







-
+







	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=stashMap.begin(); it!=stashMap.end(); ++it)
	for(stashmap_t::iterator it=getRepo().stashMap.begin(); it!=getRepo().stashMap.end(); ++it)
	{
		if(stash_name == it.key())
		{
			QMessageBox::critical(this, tr("Error"), tr("This stash already exists"));
			return;
		}
	}
1950
1951
1952
1953
1954
1955
1956
1957
1958


1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971


1972
1973
1974
1975
1976
1977
1978
1950
1951
1952
1953
1954
1955
1956


1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969


1970
1971
1972
1973
1974
1975
1976
1977
1978







-
-
+
+











-
-
+
+







	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 = stashMap.find(*it);
		Q_ASSERT(id_it!=stashMap.end());
		stashmap_t::iterator id_it = getRepo().stashMap.find(*it);
		Q_ASSERT(id_it!=getRepo().stashMap.end());

		if(!bridge.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 = stashMap.find(*it);
		Q_ASSERT(id_it!=stashMap.end());
		stashmap_t::iterator id_it = getRepo().stashMap.find(*it);
		Q_ASSERT(id_it!=getRepo().stashMap.end());

		if(!bridge.stashDrop(*id_it))
		{
			log(tr("Stash deletion aborted due to errors")+"\n");
			return;
		}
	}
1991
1992
1993
1994
1995
1996
1997
1998
1999


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
1991
1992
1993
1994
1995
1996
1997


1998
1999
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







-
-
+
+




















-
-
+
+








	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 = stashMap.find(*it);
		Q_ASSERT(id_it!=stashMap.end());
		stashmap_t::iterator id_it = getRepo().stashMap.find(*it);
		Q_ASSERT(id_it!=getRepo().stashMap.end());

		if(!bridge.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 = stashMap.find(*stashes.begin());
	Q_ASSERT(id_it!=stashMap.end());
	stashmap_t::iterator id_it = getRepo().stashMap.find(*stashes.begin());
	Q_ASSERT(id_it!=getRepo().stashMap.end());

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

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