Mercurial > hg > easyhg
comparison src/mainwindow.cpp @ 548:dca5bd5b2a06
Merge from branch "fswatcher"
author | Chris Cannam |
---|---|
date | Tue, 14 Feb 2012 17:55:39 +0000 |
parents | 4edb47f8c3a3 |
children | 06f7ae09015f |
comparison
equal
deleted
inserted
replaced
537:a4e699d32a9a | 548:dca5bd5b2a06 |
---|---|
50 #include "annotatedialog.h" | 50 #include "annotatedialog.h" |
51 #include "version.h" | 51 #include "version.h" |
52 #include "workstatuswidget.h" | 52 #include "workstatuswidget.h" |
53 #include "hgignoredialog.h" | 53 #include "hgignoredialog.h" |
54 #include "versiontester.h" | 54 #include "versiontester.h" |
55 #include "fswatcher.h" | |
55 | 56 |
56 | 57 |
57 MainWindow::MainWindow(QString myDirPath) : | 58 MainWindow::MainWindow(QString myDirPath) : |
58 m_myDirPath(myDirPath), | 59 m_myDirPath(myDirPath), |
59 m_helpDialog(0), | 60 m_helpDialog(0) |
60 m_fsWatcherGeneralTimer(0), | |
61 m_fsWatcherRestoreTimer(0), | |
62 m_fsWatcherSuspended(false) | |
63 { | 61 { |
64 setWindowIcon(QIcon(":images/easyhg-icon.png")); | 62 setWindowIcon(QIcon(":images/easyhg-icon.png")); |
65 | 63 |
66 QString wndTitle; | 64 QString wndTitle; |
67 | 65 |
68 m_showAllFiles = false; | 66 m_showAllFiles = false; |
69 | 67 |
70 m_fsWatcher = 0; | 68 m_fsWatcher = new FsWatcher(); |
69 m_fsWatcherToken = m_fsWatcher->getNewToken(); | |
70 m_commandSequenceInProgress = false; | |
71 connect(m_fsWatcher, SIGNAL(changed()), this, SLOT(checkFilesystem())); | |
72 | |
71 m_commitsSincePush = 0; | 73 m_commitsSincePush = 0; |
72 m_shouldHgStat = true; | 74 m_shouldHgStat = true; |
73 | 75 |
74 createActions(); | 76 createActions(); |
75 createMenus(); | 77 createMenus(); |
249 | 251 |
250 void MainWindow::hgStat() | 252 void MainWindow::hgStat() |
251 { | 253 { |
252 QStringList params; | 254 QStringList params; |
253 | 255 |
254 if (m_showAllFiles) { | 256 // We always stat all files, regardless of whether we're showing |
255 params << "stat" << "-A"; | 257 // them all, because we need them for the filesystem monitor |
256 } else { | 258 params << "stat" << "-A"; |
257 params << "stat" << "-ardum"; | |
258 } | |
259 | 259 |
260 m_lastStatOutput = ""; | 260 m_lastStatOutput = ""; |
261 | |
262 // We're about to do a stat, so we can silently bring ourselves | |
263 // up-to-date on any file changes to this point | |
264 (void)m_fsWatcher->getChangedPaths(m_fsWatcherToken); | |
261 | 265 |
262 m_runner->requestAction(HgAction(ACT_STAT, m_workFolderPath, params)); | 266 m_runner->requestAction(HgAction(ACT_STAT, m_workFolderPath, params)); |
263 } | 267 } |
264 | 268 |
265 void MainWindow::hgQueryPaths() | 269 void MainWindow::hgQueryPaths() |
1299 m_lastRevertedFiles.clear(); | 1303 m_lastRevertedFiles.clear(); |
1300 m_mergeTargetRevision = ""; | 1304 m_mergeTargetRevision = ""; |
1301 m_mergeCommitComment = ""; | 1305 m_mergeCommitComment = ""; |
1302 m_stateUnknown = true; | 1306 m_stateUnknown = true; |
1303 m_needNewLog = true; | 1307 m_needNewLog = true; |
1304 if (m_fsWatcher) { | |
1305 delete m_fsWatcherGeneralTimer; | |
1306 m_fsWatcherGeneralTimer = 0; | |
1307 delete m_fsWatcherRestoreTimer; | |
1308 m_fsWatcherRestoreTimer = 0; | |
1309 delete m_fsWatcher; | |
1310 m_fsWatcher = 0; | |
1311 } | |
1312 } | 1308 } |
1313 | 1309 |
1314 void MainWindow::hgServe() | 1310 void MainWindow::hgServe() |
1315 { | 1311 { |
1316 QStringList params; | 1312 QStringList params; |
1819 updateToolBarStyle(); | 1815 updateToolBarStyle(); |
1820 hgRefresh(); | 1816 hgRefresh(); |
1821 } | 1817 } |
1822 } | 1818 } |
1823 | 1819 |
1824 void MainWindow::updateFileSystemWatcher() | 1820 void MainWindow::updateFsWatcher() |
1825 { | 1821 { |
1826 bool justCreated = false; | 1822 m_fsWatcher->setWorkDirPath(m_workFolderPath); |
1827 if (!m_fsWatcher) { | 1823 m_fsWatcher->setTrackedFilePaths(m_hgTabs->getFileStates().trackedFiles()); |
1828 m_fsWatcher = new QFileSystemWatcher(); | |
1829 justCreated = true; | |
1830 } | |
1831 | |
1832 // QFileSystemWatcher will refuse to add a file or directory to | |
1833 // its watch list that it is already watching -- fine, that's what | |
1834 // we want -- but it prints a warning when this happens, which is | |
1835 // annoying because it would be the normal case for us. So we'll | |
1836 // check for duplicates ourselves. | |
1837 QSet<QString> alreadyWatched; | |
1838 QStringList dl(m_fsWatcher->directories()); | |
1839 foreach (QString d, dl) alreadyWatched.insert(d); | |
1840 | |
1841 std::deque<QString> pending; | |
1842 pending.push_back(m_workFolderPath); | |
1843 | |
1844 while (!pending.empty()) { | |
1845 | |
1846 QString path = pending.front(); | |
1847 pending.pop_front(); | |
1848 if (!alreadyWatched.contains(path)) { | |
1849 m_fsWatcher->addPath(path); | |
1850 DEBUG << "Added to file system watcher: " << path << endl; | |
1851 } | |
1852 | |
1853 QDir d(path); | |
1854 if (d.exists()) { | |
1855 d.setFilter(QDir::Dirs | QDir::NoDotAndDotDot | | |
1856 QDir::Readable | QDir::NoSymLinks); | |
1857 foreach (QString entry, d.entryList()) { | |
1858 if (entry.startsWith('.')) continue; | |
1859 QString entryPath = d.absoluteFilePath(entry); | |
1860 pending.push_back(entryPath); | |
1861 } | |
1862 } | |
1863 } | |
1864 | |
1865 // The general timer isn't really related to the fs watcher | |
1866 // object, it just does something similar -- every now and then we | |
1867 // do a refresh just to update the history dates etc | |
1868 | |
1869 m_fsWatcherGeneralTimer = new QTimer(this); | |
1870 connect(m_fsWatcherGeneralTimer, SIGNAL(timeout()), | |
1871 this, SLOT(checkFilesystem())); | |
1872 m_fsWatcherGeneralTimer->setInterval(30 * 60 * 1000); // half an hour | |
1873 m_fsWatcherGeneralTimer->start(); | |
1874 | |
1875 if (justCreated) { | |
1876 connect(m_fsWatcher, SIGNAL(directoryChanged(QString)), | |
1877 this, SLOT(fsDirectoryChanged(QString))); | |
1878 connect(m_fsWatcher, SIGNAL(fileChanged(QString)), | |
1879 this, SLOT(fsFileChanged(QString))); | |
1880 } | |
1881 } | |
1882 | |
1883 void MainWindow::suspendFileSystemWatcher() | |
1884 { | |
1885 DEBUG << "MainWindow::suspendFileSystemWatcher" << endl; | |
1886 if (m_fsWatcher) { | |
1887 m_fsWatcherSuspended = true; | |
1888 if (m_fsWatcherRestoreTimer) { | |
1889 delete m_fsWatcherRestoreTimer; | |
1890 m_fsWatcherRestoreTimer = 0; | |
1891 } | |
1892 m_fsWatcherGeneralTimer->stop(); | |
1893 } | |
1894 } | |
1895 | |
1896 void MainWindow::restoreFileSystemWatcher() | |
1897 { | |
1898 DEBUG << "MainWindow::restoreFileSystemWatcher" << endl; | |
1899 if (m_fsWatcherRestoreTimer) delete m_fsWatcherRestoreTimer; | |
1900 | |
1901 // The restore timer is used to leave a polite interval between | |
1902 // being asked to restore the watcher and actually doing so. It's | |
1903 // a single shot timer each time it's used, but we don't use | |
1904 // QTimer::singleShot because we want to stop the previous one if | |
1905 // it's running (via deleting it) | |
1906 | |
1907 m_fsWatcherRestoreTimer = new QTimer(this); | |
1908 connect(m_fsWatcherRestoreTimer, SIGNAL(timeout()), | |
1909 this, SLOT(actuallyRestoreFileSystemWatcher())); | |
1910 m_fsWatcherRestoreTimer->setInterval(1000); | |
1911 m_fsWatcherRestoreTimer->setSingleShot(true); | |
1912 m_fsWatcherRestoreTimer->start(); | |
1913 } | |
1914 | |
1915 void MainWindow::actuallyRestoreFileSystemWatcher() | |
1916 { | |
1917 DEBUG << "MainWindow::actuallyRestoreFileSystemWatcher" << endl; | |
1918 if (m_fsWatcher) { | |
1919 m_fsWatcherSuspended = false; | |
1920 m_fsWatcherGeneralTimer->start(); | |
1921 } | |
1922 } | 1824 } |
1923 | 1825 |
1924 void MainWindow::checkFilesystem() | 1826 void MainWindow::checkFilesystem() |
1925 { | 1827 { |
1926 DEBUG << "MainWindow::checkFilesystem" << endl; | 1828 DEBUG << "MainWindow::checkFilesystem" << endl; |
1927 hgRefresh(); | 1829 if (!m_commandSequenceInProgress) { |
1928 } | 1830 if (!m_fsWatcher->getChangedPaths(m_fsWatcherToken).empty()) { |
1929 | 1831 hgRefresh(); |
1930 void MainWindow::fsDirectoryChanged(QString d) | 1832 return; |
1931 { | 1833 } |
1932 DEBUG << "MainWindow::fsDirectoryChanged " << d << endl; | 1834 } |
1933 if (!m_fsWatcherSuspended) { | 1835 updateFsWatcher(); |
1934 hgStat(); | |
1935 } | |
1936 } | |
1937 | |
1938 void MainWindow::fsFileChanged(QString f) | |
1939 { | |
1940 DEBUG << "MainWindow::fsFileChanged " << f << endl; | |
1941 if (!m_fsWatcherSuspended) { | |
1942 hgStat(); | |
1943 } | |
1944 } | 1836 } |
1945 | 1837 |
1946 QString MainWindow::format1(QString head) | 1838 QString MainWindow::format1(QString head) |
1947 { | 1839 { |
1948 return QString("<qt><h3>%1</h3></qt>").arg(head); | 1840 return QString("<qt><h3>%1</h3></qt>").arg(head); |
2086 output); | 1978 output); |
2087 } | 1979 } |
2088 | 1980 |
2089 void MainWindow::commandStarting(HgAction action) | 1981 void MainWindow::commandStarting(HgAction action) |
2090 { | 1982 { |
2091 // Annoyingly, hg stat actually modifies the working directory -- | 1983 m_commandSequenceInProgress = true; |
2092 // it creates files called hg-checklink and hg-checkexec to test | 1984 } |
2093 // properties of the filesystem. For safety's sake, suspend the | 1985 |
2094 // fs watcher while running commands, and restore it shortly after | 1986 void MainWindow::commandFailed(HgAction action, QString stdErr, QString stdOut) |
2095 // a command has finished. | |
2096 | |
2097 if (action.action == ACT_STAT) { | |
2098 suspendFileSystemWatcher(); | |
2099 } | |
2100 } | |
2101 | |
2102 void MainWindow::commandFailed(HgAction action, QString stderr, QString stdout) | |
2103 { | 1987 { |
2104 DEBUG << "MainWindow::commandFailed" << endl; | 1988 DEBUG << "MainWindow::commandFailed" << endl; |
2105 restoreFileSystemWatcher(); | 1989 |
1990 m_commandSequenceInProgress = false; | |
2106 | 1991 |
2107 QString setstr; | 1992 QString setstr; |
2108 #ifdef Q_OS_MAC | 1993 #ifdef Q_OS_MAC |
2109 setstr = tr("Preferences"); | 1994 setstr = tr("Preferences"); |
2110 #else | 1995 #else |
2128 MoreInformationDialog::warning | 2013 MoreInformationDialog::warning |
2129 (this, | 2014 (this, |
2130 tr("Failed to run Mercurial"), | 2015 tr("Failed to run Mercurial"), |
2131 tr("Failed to run Mercurial"), | 2016 tr("Failed to run Mercurial"), |
2132 tr("The Mercurial program either could not be found or failed to run.<br><br>Check that the Mercurial program path is correct in %1.").arg(setstr), | 2017 tr("The Mercurial program either could not be found or failed to run.<br><br>Check that the Mercurial program path is correct in %1.").arg(setstr), |
2133 stderr); | 2018 stdErr); |
2134 settings(SettingsDialog::PathsTab); | 2019 settings(SettingsDialog::PathsTab); |
2135 return; | 2020 return; |
2136 case ACT_TEST_HG_EXT: | 2021 case ACT_TEST_HG_EXT: |
2137 MoreInformationDialog::warning | 2022 MoreInformationDialog::warning |
2138 (this, | 2023 (this, |
2139 tr("Failed to run Mercurial"), | 2024 tr("Failed to run Mercurial"), |
2140 tr("Failed to run Mercurial with extension enabled"), | 2025 tr("Failed to run Mercurial with extension enabled"), |
2141 tr("The Mercurial program failed to run with the EasyMercurial interaction extension enabled.<br>This may indicate an installation problem.<br><br>You may be able to continue working if you switch off “Use EasyHg Mercurial Extension” in %1. Note that remote repositories that require authentication might not work if you do this.").arg(setstr), | 2026 tr("The Mercurial program failed to run with the EasyMercurial interaction extension enabled.<br>This may indicate an installation problem.<br><br>You may be able to continue working if you switch off “Use EasyHg Mercurial Extension” in %1. Note that remote repositories that require authentication might not work if you do this.").arg(setstr), |
2142 stderr); | 2027 stdErr); |
2143 settings(SettingsDialog::PathsTab); | 2028 settings(SettingsDialog::PathsTab); |
2144 return; | 2029 return; |
2145 case ACT_CLONEFROMREMOTE: | 2030 case ACT_CLONEFROMREMOTE: |
2146 // if clone fails, we have no repo | 2031 // if clone fails, we have no repo |
2147 m_workFolderPath = ""; | 2032 m_workFolderPath = ""; |
2148 enableDisableActions(); | 2033 enableDisableActions(); |
2149 break; // go on to default report | 2034 break; // go on to default report |
2150 case ACT_INCOMING: | 2035 case ACT_INCOMING: |
2151 if (stderr.contains("authorization failed")) { | 2036 if (stdErr.contains("authorization failed")) { |
2152 reportAuthFailed(stderr); | 2037 reportAuthFailed(stdErr); |
2153 return; | 2038 return; |
2154 } else if (stderr.contains("entry cancelled")) { | 2039 } else if (stdErr.contains("entry cancelled")) { |
2155 // ignore this, user cancelled username or password dialog | 2040 // ignore this, user cancelled username or password dialog |
2156 return; | 2041 return; |
2157 } else { | 2042 } else { |
2158 // Incoming returns non-zero code and no stderr if the | 2043 // Incoming returns non-zero code and no stdErr if the |
2159 // check was successful but there are no changes | 2044 // check was successful but there are no changes |
2160 // pending. This is the only case where we need to remove | 2045 // pending. This is the only case where we need to remove |
2161 // warning messages, because it's the only case where a | 2046 // warning messages, because it's the only case where a |
2162 // non-zero code can be returned even though the command | 2047 // non-zero code can be returned even though the command |
2163 // has for our purposes succeeded | 2048 // has for our purposes succeeded |
2164 QString replaced = stderr; | 2049 QString replaced = stdErr; |
2165 while (1) { | 2050 while (1) { |
2166 QString r1 = replaced; | 2051 QString r1 = replaced; |
2167 r1.replace(QRegExp("warning: [^\\n]*"), ""); | 2052 r1.replace(QRegExp("warning: [^\\n]*"), ""); |
2168 if (r1 == replaced) break; | 2053 if (r1 == replaced) break; |
2169 replaced = r1.trimmed(); | 2054 replaced = r1.trimmed(); |
2173 return; | 2058 return; |
2174 } | 2059 } |
2175 } | 2060 } |
2176 break; // go on to default report | 2061 break; // go on to default report |
2177 case ACT_PULL: | 2062 case ACT_PULL: |
2178 if (stderr.contains("authorization failed")) { | 2063 if (stdErr.contains("authorization failed")) { |
2179 reportAuthFailed(stderr); | 2064 reportAuthFailed(stdErr); |
2180 return; | 2065 return; |
2181 } else if (stderr.contains("entry cancelled")) { | 2066 } else if (stdErr.contains("entry cancelled")) { |
2182 // ignore this, user cancelled username or password dialog | 2067 // ignore this, user cancelled username or password dialog |
2183 return; | 2068 return; |
2184 } else if (stderr.contains("no changes found") || stdout.contains("no changes found")) { | 2069 } else if (stdErr.contains("no changes found") || stdOut.contains("no changes found")) { |
2185 // success: hg 2.1 starts returning failure code for empty pull/push | 2070 // success: hg 2.1 starts returning failure code for empty pull/push |
2186 commandCompleted(action, stdout); | 2071 m_commandSequenceInProgress = true; // there may be further commands |
2072 commandCompleted(action, stdOut); | |
2187 return; | 2073 return; |
2188 } | 2074 } |
2189 break; // go on to default report | 2075 break; // go on to default report |
2190 case ACT_PUSH: | 2076 case ACT_PUSH: |
2191 if (stderr.contains("creates new remote head")) { | 2077 if (stdErr.contains("creates new remote head")) { |
2192 reportNewRemoteHeads(stderr); | 2078 reportNewRemoteHeads(stdErr); |
2193 return; | 2079 return; |
2194 } else if (stderr.contains("authorization failed")) { | 2080 } else if (stdErr.contains("authorization failed")) { |
2195 reportAuthFailed(stderr); | 2081 reportAuthFailed(stdErr); |
2196 return; | 2082 return; |
2197 } else if (stderr.contains("entry cancelled")) { | 2083 } else if (stdErr.contains("entry cancelled")) { |
2198 // ignore this, user cancelled username or password dialog | 2084 // ignore this, user cancelled username or password dialog |
2199 return; | 2085 return; |
2200 } else if (stderr.contains("no changes found") || stdout.contains("no changes found")) { | 2086 } else if (stdErr.contains("no changes found") || stdOut.contains("no changes found")) { |
2201 // success: hg 2.1 starts returning failure code for empty pull/push | 2087 // success: hg 2.1 starts returning failure code for empty pull/push |
2202 commandCompleted(action, stdout); | 2088 m_commandSequenceInProgress = true; // there may be further commands |
2089 commandCompleted(action, stdOut); | |
2203 return; | 2090 return; |
2204 } | 2091 } |
2205 break; // go on to default report | 2092 break; // go on to default report |
2206 case ACT_QUERY_HEADS_ACTIVE: | 2093 case ACT_QUERY_HEADS_ACTIVE: |
2207 case ACT_QUERY_HEADS: | 2094 case ACT_QUERY_HEADS: |
2208 // fails if repo is empty; we don't care (if there's a genuine | 2095 // fails if repo is empty; we don't care (if there's a genuine |
2209 // problem, something else will fail too). Pretend it | 2096 // problem, something else will fail too). Pretend it |
2210 // succeeded, so that any further actions that are contingent | 2097 // succeeded, so that any further actions that are contingent |
2211 // on the success of the heads query get carried out properly. | 2098 // on the success of the heads query get carried out properly. |
2099 m_commandSequenceInProgress = true; // there may be further commands | |
2212 commandCompleted(action, ""); | 2100 commandCompleted(action, ""); |
2213 return; | 2101 return; |
2214 case ACT_FOLDERDIFF: | 2102 case ACT_FOLDERDIFF: |
2215 case ACT_CHGSETDIFF: | 2103 case ACT_CHGSETDIFF: |
2216 // external program, unlikely to be anything useful in stderr | 2104 // external program, unlikely to be anything useful in stdErr |
2217 // and some return with failure codes when something as basic | 2105 // and some return with failure codes when something as basic |
2218 // as the user closing the window via the wm happens | 2106 // as the user closing the window via the wm happens |
2219 return; | 2107 return; |
2220 case ACT_MERGE: | 2108 case ACT_MERGE: |
2221 if (stderr.contains("working directory ancestor")) { | 2109 if (stdErr.contains("working directory ancestor")) { |
2222 // arguably we should prevent this upfront, but that's | 2110 // arguably we should prevent this upfront, but that's |
2223 // trickier! | 2111 // trickier! |
2224 MoreInformationDialog::information | 2112 MoreInformationDialog::information |
2225 (this, tr("Merge"), tr("Merge has no effect"), | 2113 (this, tr("Merge"), tr("Merge has no effect"), |
2226 tr("You asked to merge a revision with one of its ancestors.<p>This has no effect, because the ancestor's changes already exist in both revisions."), | 2114 tr("You asked to merge a revision with one of its ancestors.<p>This has no effect, because the ancestor's changes already exist in both revisions."), |
2227 stderr); | 2115 stdErr); |
2228 return; | 2116 return; |
2229 } | 2117 } |
2230 // else fall through | 2118 // else fall through |
2231 case ACT_RETRY_MERGE: | 2119 case ACT_RETRY_MERGE: |
2232 MoreInformationDialog::information | 2120 MoreInformationDialog::information |
2233 (this, tr("Merge"), tr("Merge failed"), | 2121 (this, tr("Merge"), tr("Merge failed"), |
2234 tr("Some files were not merged successfully.<p>You can Merge again to repeat the interactive merge; use Revert to abandon the merge entirely; or edit the files that are in conflict in an editor and, when you are happy with them, choose Mark Resolved in each file's right-button menu."), | 2122 tr("Some files were not merged successfully.<p>You can Merge again to repeat the interactive merge; use Revert to abandon the merge entirely; or edit the files that are in conflict in an editor and, when you are happy with them, choose Mark Resolved in each file's right-button menu."), |
2235 stderr); | 2123 stdErr); |
2236 m_mergeCommitComment = ""; | 2124 m_mergeCommitComment = ""; |
2237 return; | 2125 return; |
2238 case ACT_STAT: | 2126 case ACT_STAT: |
2239 break; // go on to default report | 2127 break; // go on to default report |
2240 default: | 2128 default: |
2249 | 2137 |
2250 MoreInformationDialog::warning | 2138 MoreInformationDialog::warning |
2251 (this, | 2139 (this, |
2252 tr("Command failed"), | 2140 tr("Command failed"), |
2253 tr("Command failed"), | 2141 tr("Command failed"), |
2254 (stderr == "" ? | 2142 (stdErr == "" ? |
2255 tr("A Mercurial command failed to run correctly. This may indicate an installation problem or some other problem with EasyMercurial.") : | 2143 tr("A Mercurial command failed to run correctly. This may indicate an installation problem or some other problem with EasyMercurial.") : |
2256 tr("A Mercurial command failed to run correctly. This may indicate an installation problem or some other problem with EasyMercurial.<br><br>See “More Details” for the command output.")), | 2144 tr("A Mercurial command failed to run correctly. This may indicate an installation problem or some other problem with EasyMercurial.<br><br>See “More Details” for the command output.")), |
2257 stderr); | 2145 stdErr); |
2258 } | 2146 } |
2259 | 2147 |
2260 void MainWindow::commandCompleted(HgAction completedAction, QString output) | 2148 void MainWindow::commandCompleted(HgAction completedAction, QString output) |
2261 { | 2149 { |
2262 // std::cerr << "commandCompleted: " << completedAction.action << std::endl; | 2150 // std::cerr << "commandCompleted: " << completedAction.action << std::endl; |
2263 | 2151 |
2264 restoreFileSystemWatcher(); | |
2265 HGACTIONS action = completedAction.action; | 2152 HGACTIONS action = completedAction.action; |
2266 | 2153 |
2267 if (action == ACT_NONE) return; | 2154 if (action == ACT_NONE) return; |
2268 | 2155 |
2269 output.replace("\r\n", "\n"); | 2156 output.replace("\r\n", "\n"); |
2318 m_currentBranch = output.trimmed(); | 2205 m_currentBranch = output.trimmed(); |
2319 break; | 2206 break; |
2320 | 2207 |
2321 case ACT_STAT: | 2208 case ACT_STAT: |
2322 m_lastStatOutput = output; | 2209 m_lastStatOutput = output; |
2323 updateFileSystemWatcher(); | |
2324 break; | 2210 break; |
2325 | 2211 |
2326 case ACT_RESOLVE_LIST: | 2212 case ACT_RESOLVE_LIST: |
2327 // This happens on every update, after the stat (above) | 2213 // This happens on every update, after the stat (above) |
2328 if (output != "") { | 2214 if (output != "") { |
2622 } | 2508 } |
2623 break; | 2509 break; |
2624 } | 2510 } |
2625 | 2511 |
2626 if (noMore) { | 2512 if (noMore) { |
2513 m_commandSequenceInProgress = false; | |
2627 m_stateUnknown = false; | 2514 m_stateUnknown = false; |
2628 enableDisableActions(); | 2515 enableDisableActions(); |
2629 m_hgTabs->updateHistory(); | 2516 m_hgTabs->updateHistory(); |
2630 updateRecentMenu(); | 2517 updateRecentMenu(); |
2518 checkFilesystem(); | |
2631 } | 2519 } |
2632 } | 2520 } |
2633 | 2521 |
2634 void MainWindow::connectActions() | 2522 void MainWindow::connectActions() |
2635 { | 2523 { |
2994 #endif | 2882 #endif |
2995 m_exitAct->setShortcuts(QKeySequence::Quit); | 2883 m_exitAct->setShortcuts(QKeySequence::Quit); |
2996 m_exitAct->setStatusTip(tr("Exit EasyMercurial")); | 2884 m_exitAct->setStatusTip(tr("Exit EasyMercurial")); |
2997 | 2885 |
2998 //Repository actions | 2886 //Repository actions |
2999 m_hgRefreshAct = new QAction(QIcon(":/images/status.png"), tr("&Refresh"), this); | 2887 m_hgRefreshAct = new QAction(QIcon(":/images/status.png"), tr("&Re-Read Working Folder"), this); |
3000 m_hgRefreshAct->setShortcut(tr("Ctrl+R")); | 2888 m_hgRefreshAct->setShortcut(tr("Ctrl+R")); |
3001 m_hgRefreshAct->setStatusTip(tr("Refresh the window to show the current state of the working folder")); | 2889 m_hgRefreshAct->setStatusTip(tr("Refresh the window to show the current state of the working folder")); |
3002 | 2890 |
3003 m_hgIncomingAct = new QAction(QIcon(":/images/incoming.png"), tr("Pre&view Incoming Changes"), this); | 2891 m_hgIncomingAct = new QAction(QIcon(":/images/incoming.png"), tr("Pre&view Incoming Changes"), this); |
3004 m_hgIncomingAct->setIconText(tr("Preview")); | 2892 m_hgIncomingAct->setIconText(tr("Preview")); |
3116 | 3004 |
3117 void MainWindow::createToolBars() | 3005 void MainWindow::createToolBars() |
3118 { | 3006 { |
3119 int sz = 32; | 3007 int sz = 32; |
3120 | 3008 |
3121 m_fileToolBar = addToolBar(tr("File")); | 3009 bool spacingReqd = false; |
3122 m_fileToolBar->setIconSize(QSize(sz, sz)); | 3010 #ifndef Q_OS_MAC |
3123 m_fileToolBar->addAction(m_openAct); | 3011 spacingReqd = true; |
3124 m_fileToolBar->addAction(m_hgRefreshAct); | 3012 #endif |
3125 m_fileToolBar->setMovable(false); | |
3126 | |
3127 m_repoToolBar = addToolBar(tr("Remote")); | |
3128 m_repoToolBar->setIconSize(QSize(sz, sz)); | |
3129 m_repoToolBar->addAction(m_hgIncomingAct); | |
3130 m_repoToolBar->addAction(m_hgPullAct); | |
3131 m_repoToolBar->addAction(m_hgPushAct); | |
3132 m_repoToolBar->setMovable(false); | |
3133 | 3013 |
3134 m_workFolderToolBar = addToolBar(tr("Work")); | 3014 m_workFolderToolBar = addToolBar(tr("Work")); |
3135 addToolBar(Qt::LeftToolBarArea, m_workFolderToolBar); | 3015 addToolBar(Qt::LeftToolBarArea, m_workFolderToolBar); |
3136 m_workFolderToolBar->setIconSize(QSize(sz, sz)); | 3016 m_workFolderToolBar->setIconSize(QSize(sz, sz)); |
3017 if (spacingReqd) { | |
3018 QWidget *w = new QWidget; | |
3019 w->setFixedHeight(6); | |
3020 m_workFolderToolBar->addWidget(w); | |
3021 } | |
3137 m_workFolderToolBar->addAction(m_hgFolderDiffAct); | 3022 m_workFolderToolBar->addAction(m_hgFolderDiffAct); |
3138 m_workFolderToolBar->addSeparator(); | 3023 m_workFolderToolBar->addSeparator(); |
3139 m_workFolderToolBar->addAction(m_hgRevertAct); | 3024 m_workFolderToolBar->addAction(m_hgRevertAct); |
3140 m_workFolderToolBar->addAction(m_hgUpdateAct); | 3025 m_workFolderToolBar->addAction(m_hgUpdateAct); |
3141 m_workFolderToolBar->addAction(m_hgCommitAct); | 3026 m_workFolderToolBar->addAction(m_hgCommitAct); |
3142 m_workFolderToolBar->addAction(m_hgMergeAct); | 3027 m_workFolderToolBar->addAction(m_hgMergeAct); |
3143 m_workFolderToolBar->addSeparator(); | 3028 m_workFolderToolBar->addSeparator(); |
3144 m_workFolderToolBar->addAction(m_hgAddAct); | 3029 m_workFolderToolBar->addAction(m_hgAddAct); |
3145 m_workFolderToolBar->addAction(m_hgRemoveAct); | 3030 m_workFolderToolBar->addAction(m_hgRemoveAct); |
3146 m_workFolderToolBar->setMovable(false); | 3031 m_workFolderToolBar->setMovable(false); |
3032 | |
3033 m_repoToolBar = addToolBar(tr("Remote")); | |
3034 m_repoToolBar->setIconSize(QSize(sz, sz)); | |
3035 if (spacingReqd) m_repoToolBar->addWidget(new QLabel(" ")); | |
3036 m_repoToolBar->addAction(m_openAct); | |
3037 if (spacingReqd) m_repoToolBar->addWidget(new QLabel(" ")); | |
3038 m_repoToolBar->addSeparator(); | |
3039 m_repoToolBar->addAction(m_hgIncomingAct); | |
3040 m_repoToolBar->addAction(m_hgPullAct); | |
3041 m_repoToolBar->addAction(m_hgPushAct); | |
3042 m_repoToolBar->setMovable(false); | |
3147 | 3043 |
3148 updateToolBarStyle(); | 3044 updateToolBarStyle(); |
3149 } | 3045 } |
3150 | 3046 |
3151 void MainWindow::updateToolBarStyle() | 3047 void MainWindow::updateToolBarStyle() |