| Chris@57 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| jtkorhonen@0 | 2 | 
| Chris@57 | 3 /* | 
| Chris@57 | 4     EasyMercurial | 
| Chris@57 | 5 | 
| Chris@98 | 6     Based on hgExplorer by Jari Korhonen | 
| Chris@57 | 7     Copyright (c) 2010 Jari Korhonen | 
| Chris@57 | 8     Copyright (c) 2010 Chris Cannam | 
| Chris@57 | 9     Copyright (c) 2010 Queen Mary, University of London | 
| Chris@57 | 10 | 
| Chris@57 | 11     This program is free software; you can redistribute it and/or | 
| Chris@57 | 12     modify it under the terms of the GNU General Public License as | 
| Chris@57 | 13     published by the Free Software Foundation; either version 2 of the | 
| Chris@57 | 14     License, or (at your option) any later version.  See the file | 
| Chris@57 | 15     COPYING included with this distribution for more information. | 
| Chris@57 | 16 */ | 
| Chris@50 | 17 | 
| jtkorhonen@0 | 18 #include <QStringList> | 
| jtkorhonen@0 | 19 #include <QDir> | 
| jtkorhonen@24 | 20 #include <QNetworkInterface> | 
| jtkorhonen@17 | 21 #include <QHostAddress> | 
| jtkorhonen@17 | 22 #include <QHostInfo> | 
| jtkorhonen@34 | 23 #include <QDesktopServices> | 
| Chris@50 | 24 #include <QStatusBar> | 
| Chris@50 | 25 #include <QMessageBox> | 
| Chris@50 | 26 #include <QMenuBar> | 
| Chris@50 | 27 #include <QApplication> | 
| Chris@50 | 28 #include <QToolBar> | 
| Chris@61 | 29 #include <QToolButton> | 
| Chris@50 | 30 #include <QSettings> | 
| Chris@90 | 31 #include <QInputDialog> | 
| jtkorhonen@0 | 32 | 
| Chris@53 | 33 #include "mainwindow.h" | 
| Chris@53 | 34 #include "settingsdialog.h" | 
| Chris@69 | 35 #include "multichoicedialog.h" | 
| Chris@64 | 36 #include "startupdialog.h" | 
| Chris@53 | 37 #include "colourset.h" | 
| Chris@62 | 38 #include "debug.h" | 
| Chris@74 | 39 #include "logparser.h" | 
| Chris@103 | 40 #include "confirmcommentdialog.h" | 
| Chris@53 | 41 | 
| jtkorhonen@0 | 42 | 
| jtkorhonen@0 | 43 MainWindow::MainWindow() | 
| jtkorhonen@0 | 44 { | 
| jtkorhonen@0 | 45     QString wndTitle; | 
| jtkorhonen@0 | 46 | 
| Chris@90 | 47     fsWatcher = 0; | 
| Chris@90 | 48 | 
| jtkorhonen@0 | 49     createActions(); | 
| jtkorhonen@0 | 50     createMenus(); | 
| jtkorhonen@0 | 51     createToolBars(); | 
| jtkorhonen@0 | 52     createStatusBar(); | 
| jtkorhonen@0 | 53 | 
| jtkorhonen@0 | 54     runner = new HgRunner(this); | 
| Chris@109 | 55     connect(runner, SIGNAL(commandCompleted(HgAction, QString)), | 
| Chris@109 | 56             this, SLOT(commandCompleted(HgAction, QString))); | 
| Chris@109 | 57     connect(runner, SIGNAL(commandFailed(HgAction, QString)), | 
| Chris@109 | 58             this, SLOT(commandFailed(HgAction, QString))); | 
| jtkorhonen@0 | 59     statusBar()->addPermanentWidget(runner); | 
| jtkorhonen@0 | 60 | 
| Chris@61 | 61     setWindowTitle(tr("EasyMercurial")); | 
| jtkorhonen@0 | 62 | 
| jtkorhonen@0 | 63     remoteRepoPath = ""; | 
| jtkorhonen@0 | 64     workFolderPath = ""; | 
| jtkorhonen@0 | 65 | 
| jtkorhonen@0 | 66     readSettings(); | 
| jtkorhonen@0 | 67 | 
| Chris@109 | 68 //    tabPage = 0; | 
| jtkorhonen@33 | 69     justMerged = false; | 
| Chris@98 | 70     hgTabs = new HgTabWidget((QWidget *) this, remoteRepoPath, workFolderPath); | 
| Chris@98 | 71     setCentralWidget(hgTabs); | 
| jtkorhonen@0 | 72 | 
| Chris@98 | 73     connect(hgTabs, SIGNAL(selectionChanged()), | 
| Chris@95 | 74             this, SLOT(enableDisableActions())); | 
| Chris@95 | 75 | 
| jtkorhonen@0 | 76     setUnifiedTitleAndToolBarOnMac(true); | 
| jtkorhonen@0 | 77     connectActions(); | 
| jtkorhonen@0 | 78     enableDisableActions(); | 
| jtkorhonen@0 | 79 | 
| Chris@64 | 80     if (firstStart) { | 
| Chris@64 | 81         startupDialog(); | 
| jtkorhonen@0 | 82     } | 
| jtkorhonen@0 | 83 | 
| Chris@64 | 84     ColourSet *cs = ColourSet::instance(); | 
| Chris@64 | 85     cs->clearDefaultNames(); | 
| Chris@64 | 86     cs->addDefaultName(""); | 
| Chris@64 | 87     cs->addDefaultName(getUserInfo()); | 
| Chris@62 | 88 | 
| Chris@72 | 89     if (workFolderPath == "") { | 
| Chris@72 | 90         open(); | 
| Chris@72 | 91     } | 
| Chris@72 | 92 | 
| Chris@109 | 93     hgQueryPaths(); | 
| jtkorhonen@0 | 94 } | 
| jtkorhonen@0 | 95 | 
| jtkorhonen@0 | 96 | 
| jtkorhonen@0 | 97 void MainWindow::closeEvent(QCloseEvent *) | 
| jtkorhonen@0 | 98 { | 
| jtkorhonen@0 | 99     writeSettings(); | 
| Chris@90 | 100     delete fsWatcher; | 
| jtkorhonen@0 | 101 } | 
| jtkorhonen@0 | 102 | 
| jtkorhonen@0 | 103 | 
| Chris@64 | 104 QString MainWindow::getUserInfo() const | 
| Chris@64 | 105 { | 
| Chris@64 | 106     QSettings settings; | 
| Chris@64 | 107     settings.beginGroup("User Information"); | 
| Chris@64 | 108     QString name = settings.value("name", getUserRealName()).toString(); | 
| Chris@64 | 109     QString email = settings.value("email", "").toString(); | 
| Chris@64 | 110 | 
| Chris@64 | 111     QString identifier; | 
| Chris@64 | 112 | 
| Chris@64 | 113     if (email != "") { | 
| Chris@64 | 114 	identifier = QString("%1 <%2>").arg(name).arg(email); | 
| Chris@64 | 115     } else { | 
| Chris@64 | 116 	identifier = name; | 
| Chris@64 | 117     } | 
| Chris@64 | 118 | 
| Chris@64 | 119     return identifier; | 
| Chris@64 | 120 } | 
| Chris@64 | 121 | 
| jtkorhonen@0 | 122 void MainWindow::about() | 
| jtkorhonen@0 | 123 { | 
| Chris@97 | 124    QMessageBox::about(this, tr("About EasyMercurial"), | 
| Chris@97 | 125                       tr("<qt><h2>About EasyMercurial</h2>" | 
| Chris@97 | 126                          "<p>EasyMercurial is a simple user interface for the " | 
| Chris@97 | 127                          "Mercurial version control system.</p>" | 
| Chris@98 | 128                          "<p>EasyMercurial is based on hgExplorer by " | 
| Chris@97 | 129                          "Jari Korhonen, with thanks.<br>EasyMercurial development carried out by " | 
| Chris@97 | 130                          "Chris Cannam for soundsoftware.ac.uk at the Centre for Digital Music, Queen Mary, University of London." | 
| Chris@97 | 131                          "<ul><li>Copyright © 2010 Jari Korhonen</li>" | 
| Chris@97 | 132                          "<li>Copyright © 2010 Chris Cannam</li>" | 
| Chris@97 | 133                          "<li>Copyright © 2010 Queen Mary, University of London</li>" | 
| Chris@97 | 134                          "</ul>" | 
| Chris@97 | 135                          "<p> This program is free software; you can redistribute it and/or " | 
| Chris@97 | 136                          "modify it under the terms of the GNU General Public License as " | 
| Chris@97 | 137                          "published by the Free Software Foundation; either version 2 of the " | 
| Chris@97 | 138                          "License, or (at your option) any later version.  See the file " | 
| Chris@97 | 139                          "COPYING included with this distribution for more information.")); | 
| jtkorhonen@0 | 140 } | 
| jtkorhonen@0 | 141 | 
| Chris@94 | 142 void MainWindow::clearSelections() | 
| Chris@94 | 143 { | 
| Chris@98 | 144     hgTabs->clearSelections(); | 
| Chris@94 | 145 } | 
| jtkorhonen@0 | 146 | 
| jtkorhonen@0 | 147 void MainWindow::hgStat() | 
| jtkorhonen@0 | 148 { | 
| Chris@109 | 149     QStringList params; | 
| Chris@109 | 150     params << "stat" << "-ardum"; | 
| Chris@109 | 151     runner->requestAction(HgAction(ACT_STAT, workFolderPath, params)); | 
| jtkorhonen@0 | 152 } | 
| jtkorhonen@0 | 153 | 
| Chris@109 | 154 void MainWindow::hgQueryPaths() | 
| Chris@74 | 155 { | 
| Chris@109 | 156     QStringList params; | 
| Chris@109 | 157     params << "paths"; | 
| Chris@109 | 158     runner->requestAction(HgAction(ACT_QUERY_PATHS, workFolderPath, params)); | 
| Chris@74 | 159 } | 
| Chris@74 | 160 | 
| Chris@109 | 161 void MainWindow::hgQueryBranch() | 
| Chris@106 | 162 { | 
| Chris@109 | 163     QStringList params; | 
| Chris@109 | 164     params << "branch"; | 
| Chris@109 | 165     runner->requestAction(HgAction(ACT_QUERY_BRANCH, workFolderPath, params)); | 
| Chris@106 | 166 } | 
| Chris@106 | 167 | 
| Chris@109 | 168 void MainWindow::hgQueryHeads() | 
| jtkorhonen@0 | 169 { | 
| Chris@109 | 170     QStringList params; | 
| Chris@109 | 171     params << "heads"; | 
| Chris@109 | 172     // on empty repos, "hg heads" will fail -- we don't care about that. | 
| Chris@109 | 173     runner->requestAction(HgAction(ACT_QUERY_HEADS, workFolderPath, params)); | 
| jtkorhonen@0 | 174 } | 
| jtkorhonen@0 | 175 | 
| jtkorhonen@0 | 176 void MainWindow::hgLog() | 
| jtkorhonen@0 | 177 { | 
| Chris@90 | 178 //!!! This needs to be incremental, except when we pull or set new repo | 
| Chris@109 | 179     QStringList params; | 
| Chris@109 | 180     params << "log"; | 
| Chris@109 | 181     params << "--template"; | 
| Chris@109 | 182     params << "id: {rev}:{node|short}\\nauthor: {author}\\nbranch: {branches}\\ntag: {tag}\\ndatetime: {date|isodate}\\ntimestamp: {date|hgdate}\\nage: {date|age}\\nparents: {parents}\\ncomment: {desc|json}\\n\\n"; | 
| Chris@109 | 183 | 
| Chris@109 | 184     runner->requestAction(HgAction(ACT_LOG, workFolderPath, params)); | 
| Chris@109 | 185 } | 
| Chris@109 | 186 | 
| Chris@109 | 187 | 
| Chris@109 | 188 void MainWindow::hgQueryParents() | 
| Chris@109 | 189 { | 
| Chris@109 | 190     QStringList params; | 
| Chris@109 | 191     params << "parents"; | 
| Chris@109 | 192     runner->requestAction(HgAction(ACT_QUERY_PARENTS, workFolderPath, params)); | 
| Chris@109 | 193 } | 
| Chris@109 | 194 | 
| Chris@109 | 195 void MainWindow::hgAnnotate() | 
| Chris@109 | 196 { | 
| Chris@109 | 197     QStringList params; | 
| Chris@109 | 198     QString currentFile;//!!! = hgTabs -> getCurrentFileListLine(); | 
| Chris@109 | 199 | 
| Chris@109 | 200     if (!currentFile.isEmpty()) | 
| jtkorhonen@0 | 201     { | 
| Chris@109 | 202         params << "annotate" << "--" << currentFile.mid(2);   //Jump over status marker characters (e.g "M ") | 
| jtkorhonen@0 | 203 | 
| Chris@109 | 204         runner->requestAction(HgAction(ACT_ANNOTATE, workFolderPath, params)); | 
| jtkorhonen@0 | 205     } | 
| jtkorhonen@0 | 206 } | 
| jtkorhonen@0 | 207 | 
| Chris@109 | 208 void MainWindow::hgResolveMark() | 
| Chris@109 | 209 { | 
| Chris@109 | 210     QStringList params; | 
| Chris@109 | 211     QString currentFile;//!!! = hgTabs -> getCurrentFileListLine(); | 
| jtkorhonen@0 | 212 | 
| Chris@109 | 213     if (!currentFile.isEmpty()) | 
| jtkorhonen@0 | 214     { | 
| Chris@109 | 215         params << "resolve" << "--mark" << "--" << currentFile.mid(2);   //Jump over status marker characters (e.g "M ") | 
| jtkorhonen@0 | 216 | 
| Chris@109 | 217         runner->requestAction(HgAction(ACT_RESOLVE_MARK, workFolderPath, params)); | 
| jtkorhonen@0 | 218     } | 
| jtkorhonen@0 | 219 } | 
| jtkorhonen@0 | 220 | 
| Chris@109 | 221 void MainWindow::hgResolveList() | 
| Chris@109 | 222 { | 
| Chris@109 | 223     QStringList params; | 
| jtkorhonen@0 | 224 | 
| Chris@109 | 225     params << "resolve" << "--list"; | 
| Chris@109 | 226     runner->requestAction(HgAction(ACT_RESOLVE_LIST, workFolderPath, params)); | 
| Chris@109 | 227 } | 
| Chris@109 | 228 | 
| Chris@109 | 229 void MainWindow::hgAdd() | 
| jtkorhonen@0 | 230 { | 
| Chris@109 | 231     QStringList params; | 
| jtkorhonen@0 | 232 | 
| Chris@109 | 233     // hgExplorer permitted adding "all" files -- I'm not sure | 
| Chris@109 | 234     // that one is a good idea, let's require the user to select | 
| jtkorhonen@0 | 235 | 
| Chris@109 | 236     QStringList files = hgTabs->getSelectedAddableFiles(); | 
| Chris@109 | 237 | 
| Chris@109 | 238     if (!files.empty()) { | 
| Chris@109 | 239         params << "add" << "--" << files; | 
| Chris@109 | 240         runner->requestAction(HgAction(ACT_ADD, workFolderPath, params)); | 
| jtkorhonen@0 | 241     } | 
| jtkorhonen@0 | 242 } | 
| jtkorhonen@0 | 243 | 
| jtkorhonen@0 | 244 | 
| Chris@98 | 245 void MainWindow::hgRemove() | 
| Chris@98 | 246 { | 
| Chris@109 | 247     QStringList params; | 
| Chris@98 | 248 | 
| Chris@109 | 249     QStringList files = hgTabs->getSelectedRemovableFiles(); | 
| Chris@98 | 250 | 
| Chris@109 | 251     //!!! todo: confirmation dialog (with file list in it) (or do we | 
| Chris@109 | 252     // need that? all it does is move the files to the removed | 
| Chris@109 | 253     // list... doesn't it?) | 
| Chris@98 | 254 | 
| Chris@109 | 255     if (!files.empty()) { | 
| Chris@109 | 256         params << "remove" << "--after" << "--force" << "--" << files; | 
| Chris@109 | 257         runner->requestAction(HgAction(ACT_REMOVE, workFolderPath, params)); | 
| Chris@109 | 258     } | 
| Chris@98 | 259 | 
| Chris@91 | 260 /*!!! | 
| Chris@98 | 261         QString currentFile;//!!! = hgTabs -> getCurrentFileListLine(); | 
| Chris@98 | 262 | 
| Chris@98 | 263         if (!currentFile.isEmpty()) | 
| jtkorhonen@5 | 264         { | 
| Chris@98 | 265             if (QMessageBox::Ok == QMessageBox::warning(this, "Remove file", "Really remove file " + currentFile.mid(2) + "?", | 
| Chris@98 | 266                 QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel)) | 
| Chris@98 | 267             { | 
| Chris@98 | 268                 params << "remove" << "--after" << "--force" << "--" << currentFile.mid(2);   //Jump over status marker characters (e.g "M ") | 
| jtkorhonen@17 | 269 | 
| Chris@98 | 270                 runner -> startHgCommand(workFolderPath, params); | 
| Chris@98 | 271                 runningAction = ACT_REMOVE; | 
| jtkorhonen@17 | 272             } | 
| jtkorhonen@5 | 273         } | 
| Chris@98 | 274         */ | 
| jtkorhonen@0 | 275 } | 
| jtkorhonen@0 | 276 | 
| jtkorhonen@0 | 277 void MainWindow::hgCommit() | 
| jtkorhonen@0 | 278 { | 
| Chris@109 | 279     QStringList params; | 
| Chris@109 | 280     QString comment; | 
| Chris@94 | 281 | 
| Chris@109 | 282     QStringList files = hgTabs->getSelectedCommittableFiles(); | 
| Chris@109 | 283     if (files.empty()) files = hgTabs->getAllCommittableFiles(); | 
| Chris@103 | 284 | 
| Chris@109 | 285     if (ConfirmCommentDialog::confirmAndGetLongComment | 
| Chris@109 | 286         (this, | 
| Chris@109 | 287          tr("Commit files"), | 
| Chris@109 | 288          tr("<h2>Commit files</h2><p>About to commit the following files:"), | 
| Chris@109 | 289          tr("<h2>Commit files</h2><p>About to commit %1 files."), | 
| Chris@109 | 290          files, | 
| Chris@109 | 291          comment)) { | 
| Chris@103 | 292 | 
| Chris@109 | 293         if ((justMerged == false) && //!!! review usage of justMerged, and how it interacts with asynchronous request queue | 
| Chris@109 | 294             !files.empty()) { | 
| Chris@109 | 295             // User wants to commit selected file(s) (and this is not merge commit, which would fail if we selected files) | 
| Chris@109 | 296             params << "commit" << "--message" << comment << "--user" << getUserInfo() << "--" << files; | 
| Chris@109 | 297         } else { | 
| Chris@109 | 298             // Commit all changes | 
| Chris@109 | 299             params << "commit" << "--message" << comment << "--user" << getUserInfo(); | 
| jtkorhonen@0 | 300         } | 
| Chris@109 | 301 | 
| Chris@109 | 302         runner->requestAction(HgAction(ACT_COMMIT, workFolderPath, params)); | 
| jtkorhonen@0 | 303     } | 
| jtkorhonen@0 | 304 } | 
| jtkorhonen@0 | 305 | 
| jtkorhonen@34 | 306 QString MainWindow::filterTag(QString tag) | 
| jtkorhonen@34 | 307 { | 
| jtkorhonen@34 | 308     for(int i = 0; i < tag.size(); i++) | 
| jtkorhonen@34 | 309     { | 
| jtkorhonen@34 | 310         if (tag[i].isLower() || tag[i].isUpper() || tag[i].isDigit() || (tag[i] == QChar('.'))) | 
| jtkorhonen@34 | 311         { | 
| jtkorhonen@34 | 312             //ok | 
| jtkorhonen@34 | 313         } | 
| jtkorhonen@34 | 314         else | 
| jtkorhonen@34 | 315         { | 
| jtkorhonen@34 | 316             tag[i] = QChar('_'); | 
| jtkorhonen@34 | 317         } | 
| jtkorhonen@34 | 318     } | 
| jtkorhonen@34 | 319     return tag; | 
| jtkorhonen@34 | 320 } | 
| jtkorhonen@34 | 321 | 
| jtkorhonen@34 | 322 | 
| jtkorhonen@34 | 323 void MainWindow::hgTag() | 
| jtkorhonen@34 | 324 { | 
| Chris@109 | 325     QStringList params; | 
| Chris@109 | 326     QString tag; | 
| jtkorhonen@34 | 327 | 
| Chris@109 | 328     if (ConfirmCommentDialog::confirmAndGetShortComment | 
| Chris@109 | 329         (this, | 
| Chris@109 | 330          tr("Tag"), | 
| Chris@109 | 331          tr("Enter tag:"), | 
| Chris@109 | 332          tag)) { | 
| Chris@109 | 333         if (!tag.isEmpty()) //!!! do something better if it is empty | 
| Chris@109 | 334         { | 
| Chris@109 | 335             params << "tag" << "--user" << getUserInfo() << filterTag(tag); | 
| Chris@109 | 336 | 
| Chris@109 | 337             runner->requestAction(HgAction(ACT_TAG, workFolderPath, params)); | 
| jtkorhonen@34 | 338         } | 
| jtkorhonen@34 | 339     } | 
| jtkorhonen@34 | 340 } | 
| jtkorhonen@34 | 341 | 
| jtkorhonen@34 | 342 | 
| jtkorhonen@34 | 343 void MainWindow::hgIgnore() | 
| jtkorhonen@34 | 344 { | 
| Chris@109 | 345     QString hgIgnorePath; | 
| Chris@109 | 346     QStringList params; | 
| Chris@109 | 347     QString editorName; | 
| Chris@109 | 348 | 
| Chris@109 | 349     hgIgnorePath = workFolderPath; | 
| Chris@109 | 350     hgIgnorePath += ".hgignore"; | 
| Chris@109 | 351 | 
| Chris@109 | 352     params << hgIgnorePath; | 
| Chris@109 | 353 | 
| Chris@109 | 354     if ((getSystem() == "Linux")) | 
| jtkorhonen@34 | 355     { | 
| Chris@109 | 356         editorName = "gedit"; | 
| Chris@109 | 357     } | 
| Chris@109 | 358     else | 
| Chris@109 | 359     { | 
| Chris@109 | 360         editorName = """C:\\Program Files\\Windows NT\\Accessories\\wordpad.exe"""; | 
| Chris@109 | 361     } | 
| jtkorhonen@34 | 362 | 
| Chris@109 | 363     HgAction action(ACT_HG_IGNORE, workFolderPath, params); | 
| Chris@109 | 364     action.executable = editorName; | 
| jtkorhonen@34 | 365 | 
| Chris@109 | 366     runner->requestAction(action); | 
| jtkorhonen@34 | 367 } | 
| jtkorhonen@34 | 368 | 
| jtkorhonen@34 | 369 | 
| jtkorhonen@34 | 370 | 
| jtkorhonen@0 | 371 void MainWindow::hgFileDiff() | 
| jtkorhonen@0 | 372 { | 
| jtkorhonen@0 | 373         QStringList params; | 
| Chris@91 | 374 /*!!! | 
| Chris@98 | 375         QString currentFile = hgTabs -> getCurrentFileListLine(); | 
| jtkorhonen@0 | 376 | 
| jtkorhonen@0 | 377         if (!currentFile.isEmpty()) | 
| jtkorhonen@0 | 378         { | 
| jtkorhonen@0 | 379             //Diff parent file against working folder file | 
| mg@41 | 380             params << "kdiff3" << "--" << currentFile.mid(2); | 
| Chris@62 | 381             runner -> startHgCommand(workFolderPath, params); | 
| jtkorhonen@0 | 382             runningAction = ACT_FILEDIFF; | 
| jtkorhonen@0 | 383         } | 
| Chris@91 | 384     */ | 
| jtkorhonen@0 | 385 } | 
| jtkorhonen@0 | 386 | 
| jtkorhonen@0 | 387 | 
| jtkorhonen@0 | 388 void MainWindow::hgFolderDiff() | 
| jtkorhonen@0 | 389 { | 
| Chris@109 | 390     QStringList params; | 
| jtkorhonen@0 | 391 | 
| Chris@109 | 392     //Diff parent against working folder (folder diff) | 
| Chris@109 | 393     params << "--config" << "extensions.extdiff=" << "extdiff" << "-p"; | 
| Chris@109 | 394 | 
| Chris@109 | 395     params << "kompare"; | 
| Chris@109 | 396 | 
| Chris@109 | 397 //    params << "kdiff3"; | 
| Chris@109 | 398     runner->requestAction(HgAction(ACT_FOLDERDIFF, workFolderPath, params)); | 
| jtkorhonen@0 | 399 } | 
| jtkorhonen@0 | 400 | 
| jtkorhonen@0 | 401 | 
| jtkorhonen@0 | 402 void MainWindow::hgChgSetDiff() | 
| jtkorhonen@0 | 403 { | 
| jtkorhonen@0 | 404         QStringList params; | 
| jtkorhonen@0 | 405 | 
| jtkorhonen@0 | 406         //Diff 2 history log versions against each other | 
| jtkorhonen@0 | 407         QString revA; | 
| jtkorhonen@0 | 408         QString revB; | 
| Chris@91 | 409 /*!!! | 
| Chris@98 | 410         hgTabs -> getHistoryDiffRevisions(revA, revB); | 
| jtkorhonen@0 | 411 | 
| jtkorhonen@0 | 412         if ((!revA.isEmpty()) && (!revB.isEmpty())) | 
| jtkorhonen@0 | 413         { | 
| jtkorhonen@0 | 414             params << "kdiff3" << "--rev" << revA << "--rev" << revB; | 
| Chris@62 | 415             runner -> startHgCommand(workFolderPath, params); | 
| jtkorhonen@0 | 416             runningAction = ACT_CHGSETDIFF; | 
| jtkorhonen@0 | 417         } | 
| jtkorhonen@0 | 418         else | 
| jtkorhonen@0 | 419         { | 
| jtkorhonen@0 | 420             QMessageBox::information(this, tr("Changeset diff"), tr("Please select two changesets from history list or heads list first.")); | 
| jtkorhonen@0 | 421         } | 
| Chris@91 | 422         */ | 
| jtkorhonen@0 | 423 } | 
| jtkorhonen@0 | 424 | 
| jtkorhonen@0 | 425 | 
| jtkorhonen@0 | 426 | 
| jtkorhonen@0 | 427 void MainWindow::hgUpdate() | 
| jtkorhonen@0 | 428 { | 
| Chris@109 | 429     QStringList params; | 
| jtkorhonen@0 | 430 | 
| Chris@109 | 431     params << "update"; | 
| Chris@109 | 432 | 
| Chris@109 | 433     runner->requestAction(HgAction(ACT_UPDATE, workFolderPath, params)); | 
| jtkorhonen@0 | 434 } | 
| jtkorhonen@0 | 435 | 
| jtkorhonen@0 | 436 | 
| jtkorhonen@0 | 437 void MainWindow::hgUpdateToRev() | 
| jtkorhonen@0 | 438 { | 
| jtkorhonen@0 | 439         QStringList params; | 
| jtkorhonen@0 | 440         QString rev; | 
| Chris@91 | 441 /*!!! | 
| Chris@98 | 442         hgTabs -> getUpdateToRevRevision(rev); | 
| jtkorhonen@0 | 443 | 
| Chris@98 | 444         hgTabs -> setCurrentIndex(WORKTAB); | 
| jtkorhonen@0 | 445         enableDisableActions(); | 
| jtkorhonen@0 | 446 | 
| jtkorhonen@0 | 447         params << "update" << "--rev" << rev << "--clean"; | 
| jtkorhonen@0 | 448 | 
| Chris@62 | 449         runner -> startHgCommand(workFolderPath, params); | 
| jtkorhonen@0 | 450 | 
| jtkorhonen@0 | 451         runningAction = ACT_UPDATE; | 
| Chris@91 | 452         */ | 
| Chris@109 | 453 | 
| jtkorhonen@0 | 454 } | 
| jtkorhonen@0 | 455 | 
| jtkorhonen@0 | 456 | 
| jtkorhonen@0 | 457 void MainWindow::hgRevert() | 
| jtkorhonen@0 | 458 { | 
| Chris@109 | 459     QStringList params; | 
| Chris@109 | 460     QString comment; | 
| Chris@98 | 461 | 
| Chris@109 | 462     QStringList files = hgTabs->getSelectedRevertableFiles(); | 
| Chris@109 | 463     if (files.empty()) files = hgTabs->getAllRevertableFiles(); | 
| Chris@109 | 464 | 
| Chris@109 | 465     if (ConfirmCommentDialog::confirmDangerousFilesAction | 
| Chris@109 | 466         (this, | 
| Chris@109 | 467          tr("Revert files"), | 
| Chris@109 | 468          tr("<h2>Revert files</h2><p>About to revert the following files to their previous committed state.  This will <b>throw away any changes</b> that you have made to these files but have not committed."), | 
| Chris@109 | 469          tr("<h2>Revert files</h2><p>About to revert %1 files.  This will <b>throw away any changes</b> that you have made to these files but have not committed."), | 
| Chris@109 | 470          files)) { | 
| Chris@109 | 471 | 
| Chris@98 | 472         if (files.empty()) { | 
| Chris@98 | 473             params << "revert" << "--no-backup"; | 
| Chris@98 | 474         } else { | 
| Chris@98 | 475             params << "revert" << "--no-backup" << "--" << files; | 
| Chris@98 | 476         } | 
| Chris@109 | 477 | 
| Chris@109 | 478         runner->requestAction(HgAction(ACT_REVERT, workFolderPath, params)); | 
| jtkorhonen@0 | 479     } | 
| jtkorhonen@0 | 480 } | 
| jtkorhonen@0 | 481 | 
| jtkorhonen@33 | 482 void MainWindow::hgRetryMerge() | 
| jtkorhonen@33 | 483 { | 
| Chris@109 | 484     QStringList params; | 
| jtkorhonen@33 | 485 | 
| Chris@109 | 486     params << "resolve" << "--all"; | 
| Chris@109 | 487     runner->requestAction(HgAction(ACT_RETRY_MERGE, workFolderPath, params)); | 
| jtkorhonen@33 | 488 } | 
| jtkorhonen@33 | 489 | 
| jtkorhonen@33 | 490 | 
| jtkorhonen@0 | 491 void MainWindow::hgMerge() | 
| jtkorhonen@0 | 492 { | 
| Chris@109 | 493     QStringList params; | 
| jtkorhonen@0 | 494 | 
| Chris@109 | 495     params << "merge"; | 
| Chris@109 | 496 | 
| Chris@109 | 497     runner->requestAction(HgAction(ACT_MERGE, workFolderPath, params)); | 
| jtkorhonen@0 | 498 } | 
| jtkorhonen@0 | 499 | 
| jtkorhonen@0 | 500 | 
| jtkorhonen@0 | 501 void MainWindow::hgCloneFromRemote() | 
| jtkorhonen@0 | 502 { | 
| Chris@109 | 503     QStringList params; | 
| jtkorhonen@0 | 504 | 
| Chris@109 | 505     if (!QDir(workFolderPath).exists()) { | 
| Chris@109 | 506         if (!QDir().mkpath(workFolderPath)) { | 
| Chris@109 | 507             DEBUG << "hgCloneFromRemote: Failed to create target path " | 
| Chris@109 | 508                   << workFolderPath << endl; | 
| Chris@109 | 509             //!!! report error | 
| Chris@109 | 510             return; | 
| Chris@104 | 511         } | 
| Chris@109 | 512     } | 
| Chris@104 | 513 | 
| Chris@109 | 514     params << "clone" << remoteRepoPath << workFolderPath; | 
| Chris@109 | 515 | 
| Chris@109 | 516     hgTabs->setWorkFolderAndRepoNames(workFolderPath, remoteRepoPath); | 
| jtkorhonen@0 | 517 | 
| Chris@109 | 518     runner->requestAction(HgAction(ACT_CLONEFROMREMOTE, workFolderPath, params)); | 
| jtkorhonen@0 | 519 } | 
| jtkorhonen@0 | 520 | 
| jtkorhonen@0 | 521 void MainWindow::hgInit() | 
| jtkorhonen@0 | 522 { | 
| Chris@109 | 523     QStringList params; | 
| jtkorhonen@0 | 524 | 
| Chris@109 | 525     params << "init"; | 
| Chris@109 | 526     params << workFolderPath; | 
| jtkorhonen@0 | 527 | 
| Chris@109 | 528     runner->requestAction(HgAction(ACT_INIT, workFolderPath, params)); | 
| jtkorhonen@0 | 529 } | 
| jtkorhonen@0 | 530 | 
| jtkorhonen@0 | 531 void MainWindow::hgIncoming() | 
| jtkorhonen@0 | 532 { | 
| Chris@109 | 533     QStringList params; | 
| jtkorhonen@0 | 534 | 
| Chris@109 | 535     params << "incoming" << "--newest-first" << remoteRepoPath; | 
| jtkorhonen@0 | 536 | 
| Chris@109 | 537     runner->requestAction(HgAction(ACT_INCOMING, workFolderPath, params)); | 
| jtkorhonen@0 | 538 } | 
| jtkorhonen@0 | 539 | 
| jtkorhonen@0 | 540 | 
| jtkorhonen@0 | 541 void MainWindow::hgPull() | 
| jtkorhonen@0 | 542 { | 
| Chris@109 | 543     QStringList params; | 
| jtkorhonen@0 | 544 | 
| Chris@109 | 545     params << "pull" << remoteRepoPath; | 
| jtkorhonen@0 | 546 | 
| Chris@109 | 547     runner->requestAction(HgAction(ACT_PULL, workFolderPath, params)); | 
| jtkorhonen@0 | 548 } | 
| jtkorhonen@0 | 549 | 
| jtkorhonen@0 | 550 | 
| jtkorhonen@0 | 551 void MainWindow::hgPush() | 
| jtkorhonen@0 | 552 { | 
| Chris@109 | 553     QStringList params; | 
| jtkorhonen@0 | 554 | 
| Chris@109 | 555     params << "push" << remoteRepoPath; | 
| jtkorhonen@0 | 556 | 
| Chris@109 | 557     runner->requestAction(HgAction(ACT_PUSH, workFolderPath, params)); | 
| jtkorhonen@0 | 558 } | 
| jtkorhonen@0 | 559 | 
| jtkorhonen@28 | 560 QString MainWindow::listAllUpIpV4Addresses() | 
| jtkorhonen@26 | 561 { | 
| jtkorhonen@28 | 562     QString ret; | 
| jtkorhonen@26 | 563     QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces(); | 
| jtkorhonen@26 | 564 | 
| jtkorhonen@26 | 565     for (int i = 0; i < ifaces.count(); i++) | 
| jtkorhonen@26 | 566     { | 
| jtkorhonen@26 | 567         QNetworkInterface iface = ifaces.at(i); | 
| jtkorhonen@26 | 568 | 
| jtkorhonen@26 | 569         if (iface.flags().testFlag(QNetworkInterface::IsUp) && !iface.flags().testFlag(QNetworkInterface::IsLoopBack)) | 
| jtkorhonen@26 | 570         { | 
| jtkorhonen@26 | 571             for (int j=0; j<iface.addressEntries().count(); j++) | 
| jtkorhonen@26 | 572             { | 
| jtkorhonen@28 | 573                 QHostAddress tmp = iface.addressEntries().at(j).ip(); | 
| jtkorhonen@28 | 574                 if (QAbstractSocket::IPv4Protocol == tmp.protocol()) | 
| jtkorhonen@24 | 575                 { | 
| jtkorhonen@28 | 576                     if (!ret.isEmpty()) | 
| jtkorhonen@28 | 577                     { | 
| jtkorhonen@28 | 578                         ret += " "; | 
| jtkorhonen@28 | 579                     } | 
| jtkorhonen@28 | 580                     ret += tmp.toString(); | 
| jtkorhonen@24 | 581                 } | 
| jtkorhonen@24 | 582             } | 
| jtkorhonen@22 | 583         } | 
| jtkorhonen@17 | 584     } | 
| jtkorhonen@28 | 585     return ret; | 
| jtkorhonen@28 | 586 } | 
| jtkorhonen@17 | 587 | 
| jtkorhonen@17 | 588 | 
| jtkorhonen@11 | 589 void MainWindow::hgServe() | 
| jtkorhonen@11 | 590 { | 
| Chris@109 | 591     QStringList params; | 
| Chris@109 | 592     QString msg; | 
| jtkorhonen@11 | 593 | 
| Chris@109 | 594     QString addrs = listAllUpIpV4Addresses(); | 
| Chris@109 | 595     QTextStream(&msg) << "Server running on address(es) (" << addrs << "), port 8000"; | 
| Chris@109 | 596     params << "serve"; | 
| jtkorhonen@11 | 597 | 
| Chris@109 | 598     runner->requestAction(HgAction(ACT_SERVE, workFolderPath, params)); | 
| Chris@109 | 599 | 
| Chris@109 | 600     QMessageBox::information(this, "Serve", msg, QMessageBox::Close); | 
| Chris@109 | 601 //!!!    runner -> killCurrentCommand(); | 
| jtkorhonen@11 | 602 } | 
| jtkorhonen@11 | 603 | 
| Chris@64 | 604 void MainWindow::startupDialog() | 
| Chris@64 | 605 { | 
| Chris@64 | 606     StartupDialog *dlg = new StartupDialog(this); | 
| Chris@65 | 607     if (dlg->exec()) firstStart = false; | 
| Chris@64 | 608 } | 
| jtkorhonen@11 | 609 | 
| Chris@69 | 610 void MainWindow::open() | 
| Chris@69 | 611 { | 
| Chris@86 | 612     bool done = false; | 
| Chris@69 | 613 | 
| Chris@86 | 614     while (!done) { | 
| Chris@69 | 615 | 
| Chris@86 | 616         MultiChoiceDialog *d = new MultiChoiceDialog | 
| Chris@86 | 617                                (tr("Open Repository"), | 
| Chris@86 | 618                                 tr("<qt><big>What would you like to open?</big></qt>"), | 
| Chris@86 | 619                                 this); | 
| Chris@69 | 620 | 
| Chris@86 | 621         d->addChoice("remote", | 
| Chris@86 | 622                      tr("<qt><center><img src=\":images/browser-64.png\"><br>Remote repository</center></qt>"), | 
| Chris@86 | 623                      tr("Open a remote Mercurial repository, by cloning from its URL into a local folder."), | 
| Chris@86 | 624                      MultiChoiceDialog::UrlToDirectoryArg); | 
| Chris@69 | 625 | 
| Chris@86 | 626         d->addChoice("local", | 
| Chris@86 | 627                      tr("<qt><center><img src=\":images/hglogo-64.png\"><br>Local repository</center></qt>"), | 
| Chris@86 | 628                      tr("Open an existing local Mercurial repository."), | 
| Chris@86 | 629                      MultiChoiceDialog::DirectoryArg); | 
| Chris@69 | 630 | 
| Chris@86 | 631         d->addChoice("init", | 
| Chris@86 | 632                      tr("<qt><center><img src=\":images/hdd_unmount-64.png\"><br>File folder</center></qt>"), | 
| Chris@86 | 633                      tr("Open a local folder, by creating a Mercurial repository in it."), | 
| Chris@86 | 634                      MultiChoiceDialog::DirectoryArg); | 
| Chris@79 | 635 | 
| Chris@86 | 636         d->setCurrentChoice("local"); | 
| Chris@86 | 637 | 
| Chris@86 | 638         if (d->exec() == QDialog::Accepted) { | 
| Chris@86 | 639 | 
| Chris@86 | 640             QString choice = d->getCurrentChoice(); | 
| Chris@86 | 641             QString arg = d->getArgument().trimmed(); | 
| Chris@86 | 642 | 
| Chris@86 | 643             bool result = false; | 
| Chris@86 | 644 | 
| Chris@86 | 645             if (choice == "local") { | 
| Chris@86 | 646                 result = openLocal(arg); | 
| Chris@86 | 647             } else if (choice == "remote") { | 
| Chris@86 | 648                 result = openRemote(arg, d->getAdditionalArgument().trimmed()); | 
| Chris@86 | 649             } else if (choice == "init") { | 
| Chris@86 | 650                 result = openInit(arg); | 
| Chris@86 | 651             } | 
| Chris@86 | 652 | 
| Chris@86 | 653             if (result) { | 
| Chris@86 | 654                 enableDisableActions(); | 
| Chris@109 | 655                 hgQueryPaths(); | 
| Chris@91 | 656                 done = true; | 
| Chris@91 | 657             } | 
| Chris@86 | 658 | 
| Chris@86 | 659         } else { | 
| Chris@86 | 660 | 
| Chris@86 | 661             // cancelled | 
| Chris@86 | 662             done = true; | 
| Chris@69 | 663         } | 
| Chris@79 | 664 | 
| Chris@86 | 665         delete d; | 
| Chris@69 | 666     } | 
| Chris@69 | 667 } | 
| Chris@69 | 668 | 
| Chris@79 | 669 bool MainWindow::complainAboutFilePath(QString arg) | 
| Chris@79 | 670 { | 
| Chris@79 | 671     QMessageBox::critical | 
| Chris@79 | 672         (this, tr("File chosen"), | 
| Chris@84 | 673          tr("<qt><b>Folder required</b><br><br>You asked to open \"%1\".<br>This is a file; to open a repository, you need to choose a folder.</qt>").arg(xmlEncode(arg))); | 
| Chris@79 | 674     return false; | 
| Chris@79 | 675 } | 
| Chris@79 | 676 | 
| Chris@79 | 677 bool MainWindow::complainAboutUnknownFolder(QString arg) | 
| Chris@79 | 678 { | 
| Chris@79 | 679     QMessageBox::critical | 
| Chris@79 | 680         (this, tr("Folder does not exist"), | 
| Chris@84 | 681          tr("<qt><b>Folder does not exist</b><br><br>You asked to open \"%1\".<br>This folder does not exist, and it cannot be created because its parent does not exist either.</qt>").arg(xmlEncode(arg))); | 
| Chris@84 | 682     return false; | 
| Chris@84 | 683 } | 
| Chris@84 | 684 | 
| Chris@84 | 685 bool MainWindow::complainAboutInitInRepo(QString arg) | 
| Chris@84 | 686 { | 
| Chris@84 | 687     QMessageBox::critical | 
| Chris@84 | 688         (this, tr("Path is in existing repository"), | 
| Chris@84 | 689          tr("<qt><b>Path is in an existing repository</b><br><br>You asked to initialise a repository at \"%1\".<br>This path is already inside an existing repository.</qt>").arg(xmlEncode(arg))); | 
| Chris@84 | 690     return false; | 
| Chris@84 | 691 } | 
| Chris@84 | 692 | 
| Chris@84 | 693 bool MainWindow::complainAboutInitFile(QString arg) | 
| Chris@84 | 694 { | 
| Chris@84 | 695     QMessageBox::critical | 
| Chris@84 | 696         (this, tr("Path is a file"), | 
| Chris@84 | 697          tr("<qt><b>Path is a file</b><br><br>You asked to initialise a repository at \"%1\".<br>This is an existing file; it is only possible to initialise in folders.</qt>").arg(xmlEncode(arg))); | 
| Chris@84 | 698     return false; | 
| Chris@84 | 699 } | 
| Chris@84 | 700 | 
| Chris@84 | 701 bool MainWindow::complainAboutCloneToExisting(QString arg) | 
| Chris@84 | 702 { | 
| Chris@84 | 703     QMessageBox::critical | 
| Chris@84 | 704         (this, tr("Path is in existing repository"), | 
| Chris@84 | 705          tr("<qt><b>Local path is in an existing repository</b><br><br>You asked to open a remote repository by cloning it to the local path \"%1\".<br>This path is already inside an existing repository.<br>Please provide a new folder name for the local repository.</qt>").arg(xmlEncode(arg))); | 
| Chris@84 | 706     return false; | 
| Chris@84 | 707 } | 
| Chris@84 | 708 | 
| Chris@84 | 709 bool MainWindow::complainAboutCloneToFile(QString arg) | 
| Chris@84 | 710 { | 
| Chris@84 | 711     QMessageBox::critical | 
| Chris@84 | 712         (this, tr("Path is a file"), | 
| Chris@84 | 713          tr("<qt><b>Local path is a file</b><br><br>You asked to open a remote repository by cloning it to the local path \"%1\".<br>This path is an existing file.<br>Please provide a new folder name for the local repository.</qt>").arg(xmlEncode(arg))); | 
| Chris@84 | 714     return false; | 
| Chris@84 | 715 } | 
| Chris@84 | 716 | 
| Chris@84 | 717 bool MainWindow::complainAboutCloneToExistingFolder(QString arg) | 
| Chris@84 | 718 { | 
| Chris@84 | 719     QMessageBox::critical | 
| Chris@84 | 720         (this, tr("Folder exists"), | 
| Chris@84 | 721          tr("<qt><b>Local folder already exists</b><br><br>You asked to open a remote repository by cloning it to the local path \"%1\".<br>This is the path of an existing folder.<br>Please provide a new folder name for the local repository.</qt>").arg(xmlEncode(arg))); | 
| Chris@79 | 722     return false; | 
| Chris@79 | 723 } | 
| Chris@79 | 724 | 
| Chris@79 | 725 bool MainWindow::askToOpenParentRepo(QString arg, QString parent) | 
| Chris@79 | 726 { | 
| Chris@79 | 727     return (QMessageBox::question | 
| Chris@84 | 728             (this, tr("Path is inside a repository"), | 
| Chris@86 | 729              tr("<qt><b>Open the repository that contains this path?</b><br><br>You asked to open \"%1\".<br>This is not the root folder of a repository.<br>But it is inside a repository, whose root is at \"%2\". <br><br>Would you like to open that repository instead?</qt>") | 
| Chris@79 | 730              .arg(xmlEncode(arg)).arg(xmlEncode(parent)), | 
| Chris@79 | 731              QMessageBox::Ok | QMessageBox::Cancel, | 
| Chris@79 | 732              QMessageBox::Ok) | 
| Chris@79 | 733             == QMessageBox::Ok); | 
| Chris@79 | 734 } | 
| Chris@79 | 735 | 
| Chris@79 | 736 bool MainWindow::askToInitExisting(QString arg) | 
| Chris@79 | 737 { | 
| Chris@79 | 738     return (QMessageBox::question | 
| Chris@84 | 739             (this, tr("Folder has no repository"), | 
| Chris@84 | 740              tr("<qt><b>Initialise a repository here?</b><br><br>You asked to open \"%1\".<br>This folder does not contain a Mercurial repository.<br><br>Would you like to initialise a repository here?</qt>") | 
| Chris@79 | 741              .arg(xmlEncode(arg)), | 
| Chris@79 | 742              QMessageBox::Ok | QMessageBox::Cancel, | 
| Chris@79 | 743              QMessageBox::Ok) | 
| Chris@79 | 744             == QMessageBox::Ok); | 
| Chris@79 | 745 } | 
| Chris@79 | 746 | 
| Chris@79 | 747 bool MainWindow::askToInitNew(QString arg) | 
| Chris@79 | 748 { | 
| Chris@79 | 749     return (QMessageBox::question | 
| Chris@84 | 750             (this, tr("Folder does not exist"), | 
| Chris@84 | 751              tr("<qt><b>Initialise a new repository?</b><br><br>You asked to open \"%1\".<br>This folder does not yet exist.<br><br>Would you like to create the folder and initialise a new empty repository in it?</qt>") | 
| Chris@84 | 752              .arg(xmlEncode(arg)), | 
| Chris@84 | 753              QMessageBox::Ok | QMessageBox::Cancel, | 
| Chris@84 | 754              QMessageBox::Ok) | 
| Chris@84 | 755             == QMessageBox::Ok); | 
| Chris@84 | 756 } | 
| Chris@84 | 757 | 
| Chris@84 | 758 bool MainWindow::askToOpenInsteadOfInit(QString arg) | 
| Chris@84 | 759 { | 
| Chris@84 | 760     return (QMessageBox::question | 
| Chris@84 | 761             (this, tr("Repository exists"), | 
| Chris@84 | 762              tr("<qt><b>Open existing repository?</b><br><br>You asked to initialise a new repository at \"%1\".<br>This folder already contains a repository.  Would you like to open it?</qt>") | 
| Chris@79 | 763              .arg(xmlEncode(arg)), | 
| Chris@79 | 764              QMessageBox::Ok | QMessageBox::Cancel, | 
| Chris@79 | 765              QMessageBox::Ok) | 
| Chris@79 | 766             == QMessageBox::Ok); | 
| Chris@79 | 767 } | 
| Chris@79 | 768 | 
| Chris@79 | 769 bool MainWindow::openLocal(QString local) | 
| Chris@79 | 770 { | 
| Chris@79 | 771     DEBUG << "open " << local << endl; | 
| Chris@79 | 772 | 
| Chris@79 | 773     FolderStatus status = getFolderStatus(local); | 
| Chris@79 | 774     QString containing = getContainingRepoFolder(local); | 
| Chris@79 | 775 | 
| Chris@79 | 776     switch (status) { | 
| Chris@79 | 777 | 
| Chris@79 | 778     case FolderHasRepo: | 
| Chris@79 | 779         // fine | 
| Chris@79 | 780         break; | 
| Chris@79 | 781 | 
| Chris@79 | 782     case FolderExists: | 
| Chris@79 | 783         if (containing != "") { | 
| Chris@79 | 784             if (!askToOpenParentRepo(local, containing)) return false; | 
| Chris@84 | 785             local = containing; | 
| Chris@79 | 786         } else { | 
| Chris@86 | 787             //!!! No -- this is likely to happen far more by accident | 
| Chris@86 | 788             // than because the user actually wanted to init something. | 
| Chris@86 | 789             // Don't ask, just politely reject. | 
| Chris@79 | 790             if (!askToInitExisting(local)) return false; | 
| Chris@79 | 791             return openInit(local); | 
| Chris@79 | 792         } | 
| Chris@79 | 793         break; | 
| Chris@79 | 794 | 
| Chris@79 | 795     case FolderParentExists: | 
| Chris@79 | 796         if (containing != "") { | 
| Chris@79 | 797             if (!askToOpenParentRepo(local, containing)) return false; | 
| Chris@84 | 798             local = containing; | 
| Chris@79 | 799         } else { | 
| Chris@79 | 800             if (!askToInitNew(local)) return false; | 
| Chris@79 | 801             return openInit(local); | 
| Chris@79 | 802         } | 
| Chris@79 | 803         break; | 
| Chris@79 | 804 | 
| Chris@79 | 805     case FolderUnknown: | 
| Chris@84 | 806         if (containing != "") { | 
| Chris@84 | 807             if (!askToOpenParentRepo(local, containing)) return false; | 
| Chris@84 | 808             local = containing; | 
| Chris@84 | 809         } else { | 
| Chris@84 | 810             return complainAboutUnknownFolder(local); | 
| Chris@84 | 811         } | 
| Chris@84 | 812         break; | 
| Chris@79 | 813 | 
| Chris@79 | 814     case FolderIsFile: | 
| Chris@79 | 815         return complainAboutFilePath(local); | 
| Chris@79 | 816     } | 
| Chris@79 | 817 | 
| Chris@79 | 818     workFolderPath = local; | 
| Chris@79 | 819     remoteRepoPath = ""; | 
| Chris@79 | 820     return true; | 
| Chris@79 | 821 } | 
| Chris@79 | 822 | 
| Chris@79 | 823 bool MainWindow::openRemote(QString remote, QString local) | 
| Chris@79 | 824 { | 
| Chris@79 | 825     DEBUG << "clone " << remote << " to " << local << endl; | 
| Chris@84 | 826 | 
| Chris@84 | 827     FolderStatus status = getFolderStatus(local); | 
| Chris@84 | 828     QString containing = getContainingRepoFolder(local); | 
| Chris@84 | 829 | 
| Chris@84 | 830     DEBUG << "status = " << status << ", containing = " << containing << endl; | 
| Chris@84 | 831 | 
| Chris@84 | 832     if (status == FolderHasRepo || containing != "") { | 
| Chris@84 | 833         return complainAboutCloneToExisting(local); | 
| Chris@84 | 834     } | 
| Chris@84 | 835 | 
| Chris@84 | 836     if (status == FolderIsFile) { | 
| Chris@84 | 837         return complainAboutCloneToFile(local); | 
| Chris@84 | 838     } | 
| Chris@84 | 839 | 
| Chris@84 | 840     if (status == FolderUnknown) { | 
| Chris@84 | 841         return complainAboutUnknownFolder(local); | 
| Chris@84 | 842     } | 
| Chris@84 | 843 | 
| Chris@84 | 844     if (status == FolderExists) { | 
| Chris@84 | 845         //!!! we can do better than this surely? | 
| Chris@84 | 846         return complainAboutCloneToExistingFolder(local); | 
| Chris@84 | 847     } | 
| Chris@84 | 848 | 
| Chris@84 | 849     workFolderPath = local; | 
| Chris@84 | 850     remoteRepoPath = remote; | 
| Chris@84 | 851     hgCloneFromRemote(); | 
| Chris@84 | 852 | 
| Chris@79 | 853     return true; | 
| Chris@79 | 854 } | 
| Chris@79 | 855 | 
| Chris@84 | 856 bool MainWindow::openInit(QString local) | 
| Chris@79 | 857 { | 
| Chris@84 | 858     DEBUG << "openInit " << local << endl; | 
| Chris@84 | 859 | 
| Chris@84 | 860     FolderStatus status = getFolderStatus(local); | 
| Chris@84 | 861     QString containing = getContainingRepoFolder(local); | 
| Chris@84 | 862 | 
| Chris@84 | 863     DEBUG << "status = " << status << ", containing = " << containing << endl; | 
| Chris@84 | 864 | 
| Chris@84 | 865     if (status == FolderHasRepo) { | 
| Chris@84 | 866         if (!askToOpenInsteadOfInit(local)) return false; | 
| Chris@84 | 867     } | 
| Chris@84 | 868 | 
| Chris@84 | 869     if (containing != "") { | 
| Chris@84 | 870         return complainAboutInitInRepo(local); | 
| Chris@84 | 871     } | 
| Chris@84 | 872 | 
| Chris@84 | 873     if (status == FolderIsFile) { | 
| Chris@84 | 874         return complainAboutInitFile(local); | 
| Chris@84 | 875     } | 
| Chris@84 | 876 | 
| Chris@84 | 877     if (status == FolderUnknown) { | 
| Chris@84 | 878         return complainAboutUnknownFolder(local); | 
| Chris@84 | 879     } | 
| Chris@84 | 880 | 
| Chris@84 | 881     workFolderPath = local; | 
| Chris@84 | 882     remoteRepoPath = ""; | 
| Chris@84 | 883     hgInit(); | 
| Chris@79 | 884     return true; | 
| Chris@79 | 885 } | 
| Chris@79 | 886 | 
| jtkorhonen@0 | 887 void MainWindow::settings() | 
| jtkorhonen@0 | 888 { | 
| Chris@69 | 889 /*!!! | 
| jtkorhonen@0 | 890     SettingsDialog *settingsDlg = new SettingsDialog(this); | 
| jtkorhonen@0 | 891     settingsDlg->setModal(true); | 
| jtkorhonen@0 | 892     settingsDlg->exec(); | 
| Chris@98 | 893     hgTabs -> clearLists(); | 
| jtkorhonen@0 | 894     enableDisableActions(); | 
| jtkorhonen@0 | 895     hgStat(); | 
| Chris@69 | 896 */ | 
| jtkorhonen@0 | 897 } | 
| jtkorhonen@0 | 898 | 
| jtkorhonen@2 | 899 #define STDOUT_NEEDS_BIG_WINDOW 512 | 
| jtkorhonen@2 | 900 #define SMALL_WND_W     500 | 
| jtkorhonen@2 | 901 #define SMALL_WND_H     300 | 
| jtkorhonen@2 | 902 | 
| jtkorhonen@2 | 903 #define BIG_WND_W       1024 | 
| jtkorhonen@2 | 904 #define BIG_WND_H       768 | 
| jtkorhonen@2 | 905 | 
| jtkorhonen@2 | 906 | 
| jtkorhonen@2 | 907 void MainWindow::presentLongStdoutToUser(QString stdo) | 
| jtkorhonen@0 | 908 { | 
| jtkorhonen@2 | 909     if (!stdo.isEmpty()) | 
| jtkorhonen@2 | 910     { | 
| jtkorhonen@2 | 911         QDialog dlg; | 
| jtkorhonen@0 | 912 | 
| jtkorhonen@2 | 913         if (stdo.length() > STDOUT_NEEDS_BIG_WINDOW) | 
| jtkorhonen@2 | 914         { | 
| jtkorhonen@2 | 915             dlg.setMinimumWidth(BIG_WND_W); | 
| jtkorhonen@2 | 916             dlg.setMinimumHeight(BIG_WND_H); | 
| jtkorhonen@2 | 917         } | 
| jtkorhonen@2 | 918         else | 
| jtkorhonen@2 | 919         { | 
| jtkorhonen@2 | 920             dlg.setMinimumWidth(SMALL_WND_W); | 
| jtkorhonen@2 | 921             dlg.setMinimumHeight(SMALL_WND_H); | 
| jtkorhonen@2 | 922         } | 
| jtkorhonen@0 | 923 | 
| jtkorhonen@2 | 924         QVBoxLayout *box = new QVBoxLayout; | 
| jtkorhonen@2 | 925         QListWidget *list = new QListWidget; | 
| jtkorhonen@2 | 926         list-> addItems(stdo.split("\n")); | 
| jtkorhonen@2 | 927         QPushButton *btn = new QPushButton(tr("Ok")); | 
| jtkorhonen@2 | 928         connect(btn, SIGNAL(clicked()), &dlg, SLOT(accept())); | 
| jtkorhonen@0 | 929 | 
| jtkorhonen@2 | 930         box -> addWidget(list); | 
| jtkorhonen@2 | 931         box -> addWidget(btn); | 
| jtkorhonen@2 | 932         dlg.setLayout(box); | 
| jtkorhonen@2 | 933 | 
| jtkorhonen@2 | 934         dlg.exec(); | 
| jtkorhonen@2 | 935     } | 
| jtkorhonen@2 | 936     else | 
| jtkorhonen@2 | 937     { | 
| Chris@98 | 938         QMessageBox::information(this, tr("EasyMercurial"), tr("Mercurial command did not return any output.")); | 
| jtkorhonen@2 | 939     } | 
| jtkorhonen@0 | 940 } | 
| jtkorhonen@0 | 941 | 
| Chris@90 | 942 void MainWindow::updateFileSystemWatcher() | 
| Chris@90 | 943 { | 
| Chris@90 | 944     //!!! this needs to be incremental when something changes | 
| Chris@90 | 945 | 
| Chris@90 | 946     delete fsWatcher; | 
| Chris@90 | 947     fsWatcher = new QFileSystemWatcher(); | 
| Chris@90 | 948     std::deque<QString> pending; | 
| Chris@90 | 949     pending.push_back(workFolderPath); | 
| Chris@90 | 950     while (!pending.empty()) { | 
| Chris@90 | 951         QString path = pending.front(); | 
| Chris@90 | 952         pending.pop_front(); | 
| Chris@90 | 953         fsWatcher->addPath(path); | 
| Chris@90 | 954         DEBUG << "Added to file system watcher: " << path << endl; | 
| Chris@90 | 955         QDir d(path); | 
| Chris@90 | 956         if (d.exists()) { | 
| Chris@90 | 957             d.setFilter(QDir::Files | QDir::Dirs | | 
| Chris@90 | 958                         QDir::NoDotAndDotDot | QDir::Readable); | 
| Chris@90 | 959             foreach (QString entry, d.entryList()) { | 
| Chris@90 | 960                 if (entry == ".hg") continue; | 
| Chris@90 | 961                 QString entryPath = d.absoluteFilePath(entry); | 
| Chris@90 | 962                 pending.push_back(entryPath); | 
| Chris@90 | 963             } | 
| Chris@90 | 964         } | 
| Chris@90 | 965     } | 
| Chris@90 | 966     connect(fsWatcher, SIGNAL(directoryChanged(QString)), | 
| Chris@90 | 967             this, SLOT(fsDirectoryChanged(QString))); | 
| Chris@90 | 968     connect(fsWatcher, SIGNAL(fileChanged(QString)), | 
| Chris@90 | 969             this, SLOT(fsFileChanged(QString))); | 
| Chris@90 | 970 } | 
| Chris@90 | 971 | 
| Chris@90 | 972 void MainWindow::fsDirectoryChanged(QString) | 
| Chris@90 | 973 { | 
| Chris@90 | 974     //!!! should just queue one of these! | 
| Chris@90 | 975     hgStat(); | 
| Chris@90 | 976 } | 
| Chris@90 | 977 | 
| Chris@90 | 978 void MainWindow::fsFileChanged(QString) | 
| Chris@90 | 979 { | 
| Chris@90 | 980     //!!! should just queue one of these! | 
| Chris@90 | 981     hgStat(); | 
| Chris@90 | 982 } | 
| Chris@90 | 983 | 
| Chris@109 | 984 void MainWindow::commandFailed(HgAction action, QString stderr) | 
| Chris@62 | 985 { | 
| Chris@62 | 986     DEBUG << "MainWindow::commandFailed" << endl; | 
| Chris@109 | 987 //    runner -> hideProgBar(); | 
| Chris@74 | 988 | 
| Chris@79 | 989     //!!! N.B hg incoming returns 1 even if successful, if there were no changes | 
| Chris@62 | 990 } | 
| Chris@62 | 991 | 
| Chris@109 | 992 void MainWindow::commandCompleted(HgAction completedAction, QString output) | 
| jtkorhonen@0 | 993 { | 
| jtkorhonen@0 | 994     bool shouldHgStat = false; | 
| jtkorhonen@0 | 995 | 
| Chris@109 | 996     HGACTIONS action = completedAction.action; | 
| Chris@109 | 997 | 
| Chris@109 | 998     if (action == ACT_NONE) return; | 
| Chris@109 | 999 | 
| Chris@109 | 1000     switch(action) { | 
| Chris@109 | 1001 | 
| Chris@109 | 1002     case ACT_QUERY_PATHS: | 
| jtkorhonen@0 | 1003     { | 
| Chris@109 | 1004         DEBUG << "stdout is " << output << endl; | 
| Chris@109 | 1005         LogParser lp(output, "="); | 
| Chris@109 | 1006         LogList ll = lp.parse(); | 
| Chris@109 | 1007         DEBUG << ll.size() << " results" << endl; | 
| Chris@109 | 1008         if (!ll.empty()) { | 
| Chris@109 | 1009             remoteRepoPath = lp.parse()[0]["default"].trimmed(); | 
| Chris@109 | 1010             DEBUG << "Set remote path to " << remoteRepoPath << endl; | 
| Chris@109 | 1011         } | 
| Chris@109 | 1012         MultiChoiceDialog::addRecentArgument("local", workFolderPath); | 
| Chris@109 | 1013         MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath); | 
| Chris@109 | 1014         hgTabs->setWorkFolderAndRepoNames(workFolderPath, remoteRepoPath); | 
| Chris@109 | 1015         enableDisableActions(); | 
| Chris@109 | 1016         break; | 
| Chris@109 | 1017     } | 
| jtkorhonen@0 | 1018 | 
| Chris@109 | 1019     case ACT_QUERY_BRANCH: | 
| Chris@109 | 1020         currentBranch = output.trimmed(); | 
| Chris@109 | 1021         hgTabs->setBranch(currentBranch); | 
| Chris@109 | 1022         break; | 
| jtkorhonen@0 | 1023 | 
| Chris@109 | 1024     case ACT_STAT: | 
| Chris@109 | 1025         hgTabs -> updateWorkFolderFileList(output); | 
| Chris@109 | 1026         updateFileSystemWatcher(); | 
| Chris@109 | 1027         break; | 
| Chris@109 | 1028 | 
| Chris@109 | 1029     case ACT_INCOMING: | 
| Chris@109 | 1030     case ACT_ANNOTATE: | 
| Chris@109 | 1031     case ACT_RESOLVE_LIST: | 
| Chris@109 | 1032     case ACT_RESOLVE_MARK: | 
| Chris@109 | 1033         presentLongStdoutToUser(output); | 
| Chris@109 | 1034         shouldHgStat = true; | 
| Chris@109 | 1035         break; | 
| Chris@109 | 1036 | 
| Chris@109 | 1037     case ACT_PULL: | 
| Chris@109 | 1038         QMessageBox::information(this, "Pull", output); | 
| Chris@109 | 1039         shouldHgStat = true; | 
| Chris@109 | 1040         break; | 
| Chris@109 | 1041 | 
| Chris@109 | 1042     case ACT_PUSH: | 
| Chris@109 | 1043         QMessageBox::information(this, "Push", output); | 
| Chris@109 | 1044         shouldHgStat = true; | 
| Chris@109 | 1045         break; | 
| Chris@109 | 1046 | 
| Chris@109 | 1047     case ACT_INIT: | 
| Chris@109 | 1048         MultiChoiceDialog::addRecentArgument("init", workFolderPath); | 
| Chris@109 | 1049         MultiChoiceDialog::addRecentArgument("local", workFolderPath); | 
| Chris@109 | 1050         enableDisableActions(); | 
| Chris@109 | 1051         shouldHgStat = true; | 
| Chris@109 | 1052         break; | 
| Chris@109 | 1053 | 
| Chris@109 | 1054     case ACT_CLONEFROMREMOTE: | 
| Chris@109 | 1055         MultiChoiceDialog::addRecentArgument("local", workFolderPath); | 
| Chris@109 | 1056         MultiChoiceDialog::addRecentArgument("remote", remoteRepoPath); | 
| Chris@109 | 1057         MultiChoiceDialog::addRecentArgument("remote", workFolderPath, true); | 
| Chris@109 | 1058         QMessageBox::information(this, "Clone", output); | 
| Chris@109 | 1059         enableDisableActions(); | 
| Chris@109 | 1060         shouldHgStat = true; | 
| Chris@109 | 1061         break; | 
| Chris@109 | 1062 | 
| Chris@109 | 1063     case ACT_LOG: | 
| Chris@109 | 1064         hgTabs -> updateLocalRepoHgLogList(output); | 
| Chris@109 | 1065         break; | 
| Chris@109 | 1066 | 
| Chris@109 | 1067     case ACT_QUERY_PARENTS: | 
| Chris@109 | 1068         foreach (Changeset *cs, currentParents) delete cs; | 
| Chris@109 | 1069         currentParents = Changeset::parseChangesets(output); | 
| Chris@109 | 1070         break; | 
| Chris@109 | 1071 | 
| Chris@109 | 1072     case ACT_QUERY_HEADS: | 
| Chris@109 | 1073         foreach (Changeset *cs, currentHeads) delete cs; | 
| Chris@109 | 1074         currentHeads = Changeset::parseChangesets(output); | 
| Chris@109 | 1075         break; | 
| Chris@109 | 1076 | 
| Chris@109 | 1077     case ACT_REMOVE: | 
| Chris@109 | 1078     case ACT_ADD: | 
| Chris@109 | 1079     case ACT_COMMIT: | 
| Chris@109 | 1080     case ACT_FILEDIFF: | 
| Chris@109 | 1081     case ACT_FOLDERDIFF: | 
| Chris@109 | 1082     case ACT_CHGSETDIFF: | 
| Chris@109 | 1083     case ACT_REVERT: | 
| Chris@109 | 1084     case ACT_SERVE: | 
| Chris@109 | 1085     case ACT_TAG: | 
| Chris@109 | 1086     case ACT_HG_IGNORE: | 
| Chris@109 | 1087         shouldHgStat = true; | 
| Chris@109 | 1088         break; | 
| Chris@109 | 1089 | 
| Chris@109 | 1090     case ACT_UPDATE: | 
| Chris@109 | 1091         QMessageBox::information(this, tr("Update"), output); | 
| Chris@109 | 1092         shouldHgStat = true; | 
| Chris@109 | 1093         break; | 
| Chris@109 | 1094 | 
| Chris@109 | 1095     case ACT_MERGE: | 
| Chris@109 | 1096         QMessageBox::information(this, tr("Merge"), output); | 
| Chris@109 | 1097         shouldHgStat = true; | 
| Chris@109 | 1098         justMerged = true; | 
| Chris@109 | 1099         break; | 
| Chris@109 | 1100 | 
| Chris@109 | 1101     case ACT_RETRY_MERGE: | 
| Chris@109 | 1102         QMessageBox::information(this, tr("Merge retry"), tr("Merge retry successful.")); | 
| Chris@109 | 1103         shouldHgStat = true; | 
| Chris@109 | 1104         justMerged = true; | 
| Chris@109 | 1105         break; | 
| Chris@109 | 1106 | 
| Chris@109 | 1107     default: | 
| Chris@109 | 1108         break; | 
| Chris@109 | 1109     } | 
| Chris@108 | 1110 | 
| Chris@109 | 1111     enableDisableActions(); | 
| Chris@74 | 1112 | 
| Chris@109 | 1113     // Typical sequence goes paths -> branch -> stat -> heads -> parents -> log | 
| Chris@109 | 1114     if (action == ACT_QUERY_PATHS) { | 
| Chris@109 | 1115         hgQueryBranch(); | 
| Chris@109 | 1116     } else if (action == ACT_QUERY_BRANCH) { | 
| Chris@109 | 1117         hgStat(); | 
| Chris@109 | 1118     } else if (action == ACT_STAT) { | 
| Chris@109 | 1119         hgQueryHeads(); | 
| Chris@109 | 1120     } else if (action == ACT_QUERY_HEADS) { | 
| Chris@109 | 1121         hgQueryParents(); | 
| Chris@109 | 1122     } else if (action == ACT_QUERY_PARENTS) { | 
| Chris@109 | 1123         hgLog(); | 
| Chris@109 | 1124     } else | 
| Chris@109 | 1125 /* Move to commandFailed | 
| Chris@109 | 1126 if ((runningAction == ACT_MERGE) && (exitCode != 0)) | 
| jtkorhonen@37 | 1127             { | 
| Chris@106 | 1128                 // If we had a failed merge, offer to retry | 
| jtkorhonen@37 | 1129                 if (QMessageBox::Ok == QMessageBox::information(this, tr("Retry merge ?"), tr("Merge attempt failed. retry ?"), QMessageBox::Ok | QMessageBox::Cancel)) | 
| jtkorhonen@37 | 1130                 { | 
| jtkorhonen@37 | 1131                     runningAction = ACT_NONE; | 
| jtkorhonen@37 | 1132                     hgRetryMerge(); | 
| jtkorhonen@37 | 1133                 } | 
| jtkorhonen@37 | 1134                 else | 
| jtkorhonen@37 | 1135                 { | 
| jtkorhonen@37 | 1136                     runningAction = ACT_NONE; | 
| jtkorhonen@37 | 1137                     hgStat(); | 
| jtkorhonen@37 | 1138                 } | 
| jtkorhonen@37 | 1139             } | 
| jtkorhonen@0 | 1140             else | 
| jtkorhonen@0 | 1141             { | 
| Chris@109 | 1142 */ | 
| Chris@109 | 1143         if (shouldHgStat) { | 
| Chris@109 | 1144             hgQueryPaths(); | 
| jtkorhonen@0 | 1145         } | 
| jtkorhonen@0 | 1146 } | 
| jtkorhonen@0 | 1147 | 
| jtkorhonen@0 | 1148 void MainWindow::connectActions() | 
| jtkorhonen@0 | 1149 { | 
| jtkorhonen@0 | 1150     connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); | 
| jtkorhonen@0 | 1151     connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); | 
| jtkorhonen@0 | 1152     connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); | 
| jtkorhonen@0 | 1153 | 
| Chris@109 | 1154     connect(hgStatAct, SIGNAL(triggered()), this, SLOT(hgQueryPaths())); | 
| jtkorhonen@0 | 1155     connect(hgRemoveAct, SIGNAL(triggered()), this, SLOT(hgRemove())); | 
| jtkorhonen@0 | 1156     connect(hgAddAct, SIGNAL(triggered()), this, SLOT(hgAdd())); | 
| jtkorhonen@0 | 1157     connect(hgCommitAct, SIGNAL(triggered()), this, SLOT(hgCommit())); | 
| jtkorhonen@0 | 1158     connect(hgFileDiffAct, SIGNAL(triggered()), this, SLOT(hgFileDiff())); | 
| jtkorhonen@0 | 1159     connect(hgFolderDiffAct, SIGNAL(triggered()), this, SLOT(hgFolderDiff())); | 
| jtkorhonen@0 | 1160     connect(hgChgSetDiffAct, SIGNAL(triggered()), this, SLOT(hgChgSetDiff())); | 
| jtkorhonen@0 | 1161     connect(hgUpdateAct, SIGNAL(triggered()), this, SLOT(hgUpdate())); | 
| jtkorhonen@0 | 1162     connect(hgRevertAct, SIGNAL(triggered()), this, SLOT(hgRevert())); | 
| jtkorhonen@0 | 1163     connect(hgMergeAct, SIGNAL(triggered()), this, SLOT(hgMerge())); | 
| jtkorhonen@33 | 1164     connect(hgRetryMergeAct, SIGNAL(triggered()), this, SLOT(hgRetryMerge())); | 
| jtkorhonen@34 | 1165     connect(hgTagAct, SIGNAL(triggered()), this, SLOT(hgTag())); | 
| jtkorhonen@34 | 1166     connect(hgIgnoreAct, SIGNAL(triggered()), this, SLOT(hgIgnore())); | 
| jtkorhonen@0 | 1167 | 
| jtkorhonen@0 | 1168     connect(settingsAct, SIGNAL(triggered()), this, SLOT(settings())); | 
| Chris@69 | 1169     connect(openAct, SIGNAL(triggered()), this, SLOT(open())); | 
| jtkorhonen@0 | 1170 | 
| jtkorhonen@0 | 1171     connect(hgInitAct, SIGNAL(triggered()), this, SLOT(hgInit())); | 
| jtkorhonen@0 | 1172     connect(hgCloneFromRemoteAct, SIGNAL(triggered()), this, SLOT(hgCloneFromRemote())); | 
| jtkorhonen@0 | 1173     connect(hgIncomingAct, SIGNAL(triggered()), this, SLOT(hgIncoming())); | 
| jtkorhonen@0 | 1174     connect(hgPullAct, SIGNAL(triggered()), this, SLOT(hgPull())); | 
| jtkorhonen@0 | 1175     connect(hgPushAct, SIGNAL(triggered()), this, SLOT(hgPush())); | 
| jtkorhonen@0 | 1176 | 
| Chris@109 | 1177 //    connect(hgTabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int))); | 
| jtkorhonen@0 | 1178 | 
| jtkorhonen@0 | 1179     connect(hgUpdateToRevAct, SIGNAL(triggered()), this, SLOT(hgUpdateToRev())); | 
| jtkorhonen@0 | 1180     connect(hgAnnotateAct, SIGNAL(triggered()), this, SLOT(hgAnnotate())); | 
| jtkorhonen@0 | 1181     connect(hgResolveListAct, SIGNAL(triggered()), this, SLOT(hgResolveList())); | 
| jtkorhonen@0 | 1182     connect(hgResolveMarkAct, SIGNAL(triggered()), this, SLOT(hgResolveMark())); | 
| jtkorhonen@11 | 1183     connect(hgServeAct, SIGNAL(triggered()), this, SLOT(hgServe())); | 
| Chris@94 | 1184     connect(clearSelectionsAct, SIGNAL(triggered()), this, SLOT(clearSelections())); | 
| jtkorhonen@0 | 1185 } | 
| Chris@109 | 1186 /*!!! | 
| jtkorhonen@0 | 1187 void MainWindow::tabChanged(int currTab) | 
| jtkorhonen@0 | 1188 { | 
| jtkorhonen@0 | 1189     tabPage = currTab; | 
| jtkorhonen@32 | 1190 | 
| jtkorhonen@0 | 1191 } | 
| Chris@109 | 1192 */ | 
| jtkorhonen@0 | 1193 void MainWindow::enableDisableActions() | 
| jtkorhonen@0 | 1194 { | 
| Chris@90 | 1195     DEBUG << "MainWindow::enableDisableActions" << endl; | 
| Chris@90 | 1196 | 
| jtkorhonen@0 | 1197     QDir localRepoDir; | 
| jtkorhonen@0 | 1198     QDir workFolderDir; | 
| jtkorhonen@0 | 1199     bool workFolderExist; | 
| jtkorhonen@0 | 1200     bool localRepoExist; | 
| jtkorhonen@0 | 1201 | 
| jtkorhonen@0 | 1202     remoteRepoActionsEnabled = true; | 
| Chris@90 | 1203     if (remoteRepoPath.isEmpty()) { | 
| jtkorhonen@0 | 1204         remoteRepoActionsEnabled = false; | 
| jtkorhonen@0 | 1205     } | 
| jtkorhonen@0 | 1206 | 
| jtkorhonen@0 | 1207     localRepoActionsEnabled = true; | 
| Chris@90 | 1208     if (workFolderPath.isEmpty()) { | 
| jtkorhonen@0 | 1209         localRepoActionsEnabled = false; | 
| jtkorhonen@0 | 1210         workFolderExist = false; | 
| jtkorhonen@0 | 1211     } | 
| jtkorhonen@0 | 1212 | 
| Chris@90 | 1213     if (!workFolderDir.exists(workFolderPath)) { | 
| jtkorhonen@0 | 1214         localRepoActionsEnabled = false; | 
| jtkorhonen@0 | 1215         workFolderExist = false; | 
| Chris@90 | 1216     } else { | 
| jtkorhonen@0 | 1217         workFolderExist = true; | 
| jtkorhonen@0 | 1218     } | 
| jtkorhonen@0 | 1219 | 
| Chris@90 | 1220     if (!localRepoDir.exists(workFolderPath + "/" + getHgDirName())) { | 
| jtkorhonen@0 | 1221         localRepoActionsEnabled = false; | 
| jtkorhonen@0 | 1222         localRepoExist = false; | 
| jtkorhonen@0 | 1223     } | 
| jtkorhonen@0 | 1224 | 
| jtkorhonen@0 | 1225     hgCloneFromRemoteAct -> setEnabled(remoteRepoActionsEnabled); | 
| jtkorhonen@0 | 1226     hgIncomingAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled); | 
| jtkorhonen@0 | 1227     hgPullAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled); | 
| jtkorhonen@0 | 1228     hgPushAct -> setEnabled(remoteRepoActionsEnabled && remoteRepoActionsEnabled); | 
| Chris@73 | 1229 /* | 
| jtkorhonen@0 | 1230     if (tabPage != WORKTAB) | 
| jtkorhonen@0 | 1231     { | 
| jtkorhonen@0 | 1232         localRepoActionsEnabled = false; | 
| jtkorhonen@0 | 1233     } | 
| Chris@73 | 1234 */ | 
| jtkorhonen@0 | 1235     hgInitAct -> setEnabled((localRepoExist == false) && (workFolderExist==true)); | 
| jtkorhonen@0 | 1236     hgStatAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@0 | 1237     hgFileDiffAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@0 | 1238     hgFolderDiffAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@0 | 1239     hgRevertAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@0 | 1240     hgAddAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@0 | 1241     hgRemoveAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@0 | 1242     hgUpdateAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@0 | 1243     hgCommitAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@0 | 1244     hgMergeAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@33 | 1245     hgRetryMergeAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@2 | 1246     hgResolveListAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@2 | 1247     hgResolveMarkAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@2 | 1248     hgAnnotateAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@11 | 1249     hgServeAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@34 | 1250     hgTagAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@34 | 1251     hgIgnoreAct -> setEnabled(localRepoActionsEnabled); | 
| jtkorhonen@0 | 1252 | 
| Chris@98 | 1253     //!!!hgTabs -> enableDisableOtherTabs(tabPage); | 
| jtkorhonen@0 | 1254 | 
| Chris@90 | 1255     DEBUG << "localRepoActionsEnabled = " << localRepoActionsEnabled << endl; | 
| Chris@98 | 1256     DEBUG << "canCommit = " << hgTabs->canCommit() << endl; | 
| Chris@90 | 1257 | 
| Chris@90 | 1258     //!!! new stuff: | 
| Chris@98 | 1259     hgAddAct->setEnabled(localRepoActionsEnabled && hgTabs->canAdd()); | 
| Chris@98 | 1260     hgRemoveAct->setEnabled(localRepoActionsEnabled && hgTabs->canRemove()); | 
| Chris@98 | 1261     hgCommitAct->setEnabled(localRepoActionsEnabled && hgTabs->canCommit()); | 
| Chris@98 | 1262     hgRevertAct->setEnabled(localRepoActionsEnabled && hgTabs->canCommit()); | 
| Chris@98 | 1263     hgFolderDiffAct->setEnabled(localRepoActionsEnabled && hgTabs->canDoDiff()); | 
| Chris@90 | 1264 | 
| Chris@108 | 1265     // A default merge makes sense if: | 
| Chris@108 | 1266     //  * there is only one parent (if there are two, we have an uncommitted merge) and | 
| Chris@108 | 1267     //  * there are exactly two heads that have the same branch as the current branch and | 
| Chris@108 | 1268     //  * our parent is one of those heads | 
| Chris@108 | 1269     // | 
| Chris@108 | 1270     // A default update makes sense if: | 
| Chris@108 | 1271     //  * there is only one parent and | 
| Chris@108 | 1272     //  * the parent is not one of the current heads | 
| Chris@108 | 1273     //!!! test this | 
| Chris@108 | 1274     bool canMerge = false; | 
| Chris@108 | 1275     bool canUpdate = false; | 
| Chris@108 | 1276     if (currentParents.size() == 1) { | 
| Chris@108 | 1277         Changeset *parent = currentParents[0]; | 
| Chris@108 | 1278         int currentBranchHeads = 0; | 
| Chris@108 | 1279         bool parentIsHead = false; | 
| Chris@108 | 1280         foreach (Changeset *head, currentHeads) { | 
| Chris@108 | 1281             DEBUG << "head branch " << head->branch() << ", current branch " << currentBranch << endl; | 
| Chris@108 | 1282             if (head->isOnBranch(currentBranch)) { | 
| Chris@108 | 1283                 ++currentBranchHeads; | 
| Chris@108 | 1284                 if (parent->id() == head->id()) { | 
| Chris@108 | 1285                     parentIsHead = true; | 
| Chris@108 | 1286                 } | 
| Chris@108 | 1287             } | 
| Chris@108 | 1288         } | 
| Chris@108 | 1289         if (currentBranchHeads == 2 && parentIsHead) { | 
| Chris@108 | 1290             canMerge = true; | 
| Chris@108 | 1291         } | 
| Chris@108 | 1292         if (!parentIsHead) { | 
| Chris@108 | 1293             canUpdate = true; | 
| Chris@108 | 1294             DEBUG << "parent id = " << parent->id() << endl; | 
| Chris@108 | 1295             DEBUG << " head ids "<<endl; | 
| Chris@108 | 1296             foreach (Changeset *h, currentHeads) { | 
| Chris@108 | 1297                 DEBUG << "head id = " << h->id() << endl; | 
| Chris@108 | 1298             } | 
| Chris@108 | 1299         } | 
| Chris@108 | 1300     } | 
| Chris@108 | 1301     hgMergeAct->setEnabled(localRepoActionsEnabled && canMerge); | 
| Chris@108 | 1302     hgUpdateAct->setEnabled(localRepoActionsEnabled && canUpdate); | 
| jtkorhonen@0 | 1303 } | 
| jtkorhonen@0 | 1304 | 
| jtkorhonen@0 | 1305 void MainWindow::createActions() | 
| jtkorhonen@0 | 1306 { | 
| jtkorhonen@0 | 1307     //File actions | 
| jtkorhonen@0 | 1308     hgInitAct = new QAction(tr("Init local repository"), this); | 
| jtkorhonen@0 | 1309     hgInitAct->setStatusTip(tr("Create an empty local repository in selected folder")); | 
| jtkorhonen@0 | 1310 | 
| jtkorhonen@0 | 1311     hgCloneFromRemoteAct = new QAction(tr("Clone from remote"), this); | 
| jtkorhonen@0 | 1312     hgCloneFromRemoteAct->setStatusTip(tr("Clone from remote repository into local repository in selected folder")); | 
| jtkorhonen@0 | 1313 | 
| Chris@69 | 1314     openAct = new QAction(QIcon(":/images/fileopen.png"), tr("Open..."), this); | 
| Chris@69 | 1315     openAct -> setStatusTip(tr("Open repository")); | 
| Chris@69 | 1316     openAct -> setIconVisibleInMenu(true); | 
| Chris@69 | 1317 | 
| jtkorhonen@0 | 1318     settingsAct = new QAction(QIcon(":/images/settings.png"), tr("Settings..."), this); | 
| jtkorhonen@0 | 1319     settingsAct -> setStatusTip(tr("View and change application settings")); | 
| jtkorhonen@0 | 1320     settingsAct -> setIconVisibleInMenu(true); | 
| jtkorhonen@0 | 1321 | 
| jtkorhonen@0 | 1322     exitAct = new QAction(QIcon(":/images/exit.png"), tr("Exit"), this); | 
| jtkorhonen@0 | 1323     exitAct->setShortcuts(QKeySequence::Quit); | 
| jtkorhonen@0 | 1324     exitAct->setStatusTip(tr("Exit application")); | 
| jtkorhonen@0 | 1325     exitAct -> setIconVisibleInMenu(true); | 
| jtkorhonen@0 | 1326 | 
| jtkorhonen@0 | 1327     //Repository actions | 
| Chris@61 | 1328     hgStatAct = new QAction(QIcon(":/images/status.png"), tr("Refresh"), this); | 
| Chris@61 | 1329     hgStatAct->setStatusTip(tr("Refresh (info of) status of workfolder files")); | 
| Chris@61 | 1330 | 
| Chris@61 | 1331     hgIncomingAct = new QAction(QIcon(":/images/incoming.png"), tr("Preview"), this); | 
| jtkorhonen@0 | 1332     hgIncomingAct -> setStatusTip(tr("View info of changesets incoming to us from remote repository (on pull operation)")); | 
| jtkorhonen@0 | 1333 | 
| Chris@61 | 1334     hgPullAct = new QAction(QIcon(":/images/pull.png"), tr("Pull"), this); | 
| jtkorhonen@0 | 1335     hgPullAct -> setStatusTip(tr("Pull changesets from remote repository to local repository")); | 
| jtkorhonen@0 | 1336 | 
| Chris@61 | 1337     hgPushAct = new QAction(QIcon(":/images/push.png"), tr("Push"), this); | 
| jtkorhonen@0 | 1338     hgPushAct->setStatusTip(tr("Push local changesets to remote repository")); | 
| jtkorhonen@0 | 1339 | 
| jtkorhonen@0 | 1340     //Workfolder actions | 
| Chris@61 | 1341     hgFileDiffAct   = new QAction(QIcon(":/images/diff.png"), tr("Diff"), this); | 
| jtkorhonen@0 | 1342     hgFileDiffAct->setStatusTip(tr("Filediff: View differences between selected working folder file and local repository file")); | 
| jtkorhonen@0 | 1343 | 
| Chris@99 | 1344     hgFolderDiffAct   = new QAction(QIcon(":/images/folderdiff.png"), tr("Diff"), this); | 
| jtkorhonen@0 | 1345     hgFolderDiffAct->setStatusTip(tr("Folderdiff: View all differences between working folder files and local repository files")); | 
| jtkorhonen@0 | 1346 | 
| jtkorhonen@0 | 1347     hgChgSetDiffAct   = new QAction(QIcon(":/images/chgsetdiff.png"), tr("View changesetdiff"), this); | 
| jtkorhonen@0 | 1348     hgChgSetDiffAct->setStatusTip(tr("Change set diff: View differences between all files of 2 repository changesets")); | 
| jtkorhonen@0 | 1349 | 
| Chris@61 | 1350     hgRevertAct = new QAction(QIcon(":/images/undo.png"), tr("Revert"), this); | 
| jtkorhonen@0 | 1351     hgRevertAct->setStatusTip(tr("Undo selected working folder file changes (return to local repository version)")); | 
| jtkorhonen@0 | 1352 | 
| Chris@61 | 1353     hgAddAct = new QAction(QIcon(":/images/add.png"), tr("Add"), this); | 
| jtkorhonen@17 | 1354     hgAddAct -> setStatusTip(tr("Add working folder file(s) (selected or all yet untracked) to local repository (on next commit)")); | 
| jtkorhonen@0 | 1355 | 
| Chris@61 | 1356     hgRemoveAct = new QAction(QIcon(":/images/remove.png"), tr("Remove"), this); | 
| jtkorhonen@0 | 1357     hgRemoveAct -> setStatusTip(tr("Remove selected working folder file from local repository (on next commit)")); | 
| jtkorhonen@0 | 1358 | 
| Chris@61 | 1359     hgUpdateAct = new QAction(QIcon(":/images/update.png"), tr("Update"), this); | 
| jtkorhonen@0 | 1360     hgUpdateAct->setStatusTip(tr("Update working folder from local repository")); | 
| jtkorhonen@0 | 1361 | 
| Chris@61 | 1362     hgCommitAct = new QAction(QIcon(":/images/commit.png"), tr("Commit"), this); | 
| jtkorhonen@20 | 1363     hgCommitAct->setStatusTip(tr("Save selected file(s) or all changed files in working folder (and all subfolders) to local repository")); | 
| jtkorhonen@0 | 1364 | 
| jtkorhonen@0 | 1365     hgMergeAct = new QAction(QIcon(":/images/merge.png"), tr("Merge"), this); | 
| jtkorhonen@0 | 1366     hgMergeAct->setStatusTip(tr("Merge two local repository changesets to working folder")); | 
| jtkorhonen@0 | 1367 | 
| jtkorhonen@0 | 1368     //Advanced actions | 
| jtkorhonen@0 | 1369     hgUpdateToRevAct = new QAction(tr("Update to revision"), this); | 
| jtkorhonen@0 | 1370     hgUpdateToRevAct -> setStatusTip(tr("Update working folder to version selected from history list")); | 
| jtkorhonen@0 | 1371 | 
| jtkorhonen@0 | 1372     hgAnnotateAct = new QAction(tr("Annotate"), this); | 
| jtkorhonen@0 | 1373     hgAnnotateAct -> setStatusTip(tr("Show line-by-line version information for selected file")); | 
| jtkorhonen@0 | 1374 | 
| jtkorhonen@0 | 1375     hgResolveListAct = new QAction(tr("Resolve (list)"), this); | 
| jtkorhonen@0 | 1376     hgResolveListAct -> setStatusTip(tr("Resolve (list): Show list of files needing merge")); | 
| jtkorhonen@0 | 1377 | 
| jtkorhonen@0 | 1378     hgResolveMarkAct = new QAction(tr("Resolve (mark)"), this); | 
| jtkorhonen@0 | 1379     hgResolveMarkAct -> setStatusTip(tr("Resolve (mark): Mark selected file status as resolved")); | 
| jtkorhonen@0 | 1380 | 
| jtkorhonen@33 | 1381     hgRetryMergeAct = new QAction(tr("Retry merge"), this); | 
| jtkorhonen@33 | 1382     hgRetryMergeAct -> setStatusTip(tr("Retry merge after failed merge attempt.")); | 
| jtkorhonen@33 | 1383 | 
| jtkorhonen@34 | 1384     hgTagAct = new QAction(tr("Tag revision"), this); | 
| jtkorhonen@34 | 1385     hgTagAct -> setStatusTip(tr("Give decsriptive name (tag) to current workfolder parent revision.")); | 
| jtkorhonen@34 | 1386 | 
| jtkorhonen@34 | 1387     hgIgnoreAct = new QAction(tr("Edit .hgignore"), this); | 
| jtkorhonen@34 | 1388     hgIgnoreAct -> setStatusTip(tr("Edit .hgignore file (file contains names of files that should be ignored by mercurial)")); | 
| jtkorhonen@34 | 1389 | 
| jtkorhonen@11 | 1390     hgServeAct = new QAction(tr("Serve (via http)"), this); | 
| jtkorhonen@11 | 1391     hgServeAct -> setStatusTip(tr("Serve local repository via http for workgroup access")); | 
| jtkorhonen@11 | 1392 | 
| jtkorhonen@0 | 1393     //Help actions | 
| jtkorhonen@0 | 1394     aboutAct = new QAction(tr("About"), this); | 
| jtkorhonen@0 | 1395     aboutAct->setStatusTip(tr("Show the application's About box")); | 
| jtkorhonen@0 | 1396 | 
| jtkorhonen@0 | 1397     aboutQtAct = new QAction(tr("About Qt"), this); | 
| jtkorhonen@0 | 1398     aboutQtAct->setStatusTip(tr("Show the Qt library's About box")); | 
| Chris@94 | 1399 | 
| Chris@94 | 1400     // Miscellaneous | 
| Chris@94 | 1401     clearSelectionsAct = new QAction(tr("Clear selections"), this); | 
| Chris@94 | 1402     clearSelectionsAct->setShortcut(Qt::Key_Escape); | 
| jtkorhonen@0 | 1403 } | 
| jtkorhonen@0 | 1404 | 
| jtkorhonen@0 | 1405 void MainWindow::createMenus() | 
| jtkorhonen@0 | 1406 { | 
| jtkorhonen@0 | 1407     fileMenu = menuBar()->addMenu(tr("File")); | 
| jtkorhonen@0 | 1408     fileMenu -> addAction(hgInitAct); | 
| jtkorhonen@0 | 1409     fileMenu -> addAction(hgCloneFromRemoteAct); | 
| Chris@94 | 1410     fileMenu->addAction(clearSelectionsAct); //!!! can't live here! | 
| jtkorhonen@0 | 1411     fileMenu -> addSeparator(); | 
| Chris@69 | 1412     fileMenu -> addAction(openAct); | 
| jtkorhonen@0 | 1413     fileMenu -> addAction(settingsAct); | 
| jtkorhonen@0 | 1414     fileMenu -> addSeparator(); | 
| jtkorhonen@0 | 1415     fileMenu -> addAction(exitAct); | 
| jtkorhonen@0 | 1416 | 
| jtkorhonen@0 | 1417     advancedMenu = menuBar()->addMenu(tr("Advanced")); | 
| jtkorhonen@0 | 1418     advancedMenu -> addAction(hgUpdateToRevAct); | 
| jtkorhonen@0 | 1419     advancedMenu -> addSeparator(); | 
| jtkorhonen@0 | 1420     advancedMenu -> addAction(hgAnnotateAct); | 
| jtkorhonen@0 | 1421     advancedMenu -> addSeparator(); | 
| jtkorhonen@33 | 1422     advancedMenu -> addAction(hgRetryMergeAct); | 
| jtkorhonen@0 | 1423     advancedMenu -> addAction(hgResolveListAct); | 
| jtkorhonen@0 | 1424     advancedMenu -> addAction(hgResolveMarkAct); | 
| jtkorhonen@11 | 1425     advancedMenu -> addSeparator(); | 
| jtkorhonen@34 | 1426     advancedMenu -> addAction(hgTagAct); | 
| jtkorhonen@34 | 1427     advancedMenu -> addSeparator(); | 
| jtkorhonen@34 | 1428     advancedMenu -> addAction(hgIgnoreAct); | 
| jtkorhonen@34 | 1429     advancedMenu -> addSeparator(); | 
| jtkorhonen@11 | 1430     advancedMenu -> addAction(hgServeAct); | 
| jtkorhonen@0 | 1431 | 
| jtkorhonen@0 | 1432     helpMenu = menuBar()->addMenu(tr("Help")); | 
| jtkorhonen@0 | 1433     helpMenu->addAction(aboutAct); | 
| jtkorhonen@0 | 1434     helpMenu->addAction(aboutQtAct); | 
| jtkorhonen@0 | 1435 } | 
| jtkorhonen@0 | 1436 | 
| jtkorhonen@0 | 1437 void MainWindow::createToolBars() | 
| jtkorhonen@0 | 1438 { | 
| jtkorhonen@0 | 1439     fileToolBar = addToolBar(tr("File")); | 
| jtkorhonen@0 | 1440     fileToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE)); | 
| Chris@69 | 1441     fileToolBar -> addAction(openAct); | 
| Chris@43 | 1442     fileToolBar -> addAction(hgStatAct); | 
| jtkorhonen@0 | 1443     fileToolBar -> addSeparator(); | 
| Chris@61 | 1444 //    fileToolBar -> addAction(hgChgSetDiffAct); | 
| jtkorhonen@0 | 1445     fileToolBar -> setMovable(false); | 
| jtkorhonen@0 | 1446 | 
| jtkorhonen@0 | 1447     repoToolBar = addToolBar(tr(REPOMENU_TITLE)); | 
| jtkorhonen@0 | 1448     repoToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE)); | 
| jtkorhonen@0 | 1449     repoToolBar->addAction(hgIncomingAct); | 
| jtkorhonen@0 | 1450     repoToolBar->addAction(hgPullAct); | 
| jtkorhonen@0 | 1451     repoToolBar->addAction(hgPushAct); | 
| jtkorhonen@0 | 1452     repoToolBar -> setMovable(false); | 
| jtkorhonen@0 | 1453 | 
| jtkorhonen@0 | 1454     workFolderToolBar = addToolBar(tr(WORKFOLDERMENU_TITLE)); | 
| jtkorhonen@0 | 1455     addToolBar(Qt::LeftToolBarArea, workFolderToolBar); | 
| jtkorhonen@0 | 1456     workFolderToolBar -> setIconSize(QSize(MY_ICON_SIZE, MY_ICON_SIZE)); | 
| Chris@61 | 1457 //    workFolderToolBar->addSeparator(); | 
| Chris@95 | 1458 //    workFolderToolBar->addAction(hgFileDiffAct); | 
| Chris@95 | 1459     workFolderToolBar->addAction(hgFolderDiffAct); | 
| jtkorhonen@0 | 1460     workFolderToolBar->addSeparator(); | 
| jtkorhonen@0 | 1461     workFolderToolBar->addAction(hgRevertAct); | 
| jtkorhonen@0 | 1462     workFolderToolBar->addAction(hgUpdateAct); | 
| jtkorhonen@0 | 1463     workFolderToolBar->addAction(hgCommitAct); | 
| jtkorhonen@0 | 1464     workFolderToolBar->addAction(hgMergeAct); | 
| jtkorhonen@0 | 1465     workFolderToolBar->addSeparator(); | 
| jtkorhonen@0 | 1466     workFolderToolBar->addAction(hgAddAct); | 
| jtkorhonen@0 | 1467     workFolderToolBar->addAction(hgRemoveAct); | 
| jtkorhonen@0 | 1468     workFolderToolBar -> setMovable(false); | 
| Chris@61 | 1469 | 
| Chris@61 | 1470     foreach (QToolButton *tb, findChildren<QToolButton *>()) { | 
| Chris@61 | 1471         tb->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); | 
| Chris@61 | 1472     } | 
| jtkorhonen@0 | 1473 } | 
| jtkorhonen@0 | 1474 | 
| jtkorhonen@0 | 1475 | 
| jtkorhonen@0 | 1476 void MainWindow::createStatusBar() | 
| jtkorhonen@0 | 1477 { | 
| jtkorhonen@0 | 1478     statusBar()->showMessage(tr("Ready")); | 
| jtkorhonen@0 | 1479 } | 
| jtkorhonen@0 | 1480 | 
| Chris@69 | 1481 | 
| Chris@69 | 1482 //!!! review these: | 
| Chris@69 | 1483 | 
| jtkorhonen@0 | 1484 void MainWindow::readSettings() | 
| jtkorhonen@0 | 1485 { | 
| jtkorhonen@0 | 1486     QDir workFolder; | 
| jtkorhonen@0 | 1487 | 
| Chris@61 | 1488     QSettings settings; | 
| jtkorhonen@0 | 1489 | 
| jtkorhonen@30 | 1490     remoteRepoPath = settings.value("remoterepopath", "").toString(); | 
| jtkorhonen@0 | 1491     workFolderPath = settings.value("workfolderpath", "").toString(); | 
| jtkorhonen@0 | 1492     if (!workFolder.exists(workFolderPath)) | 
| jtkorhonen@0 | 1493     { | 
| jtkorhonen@0 | 1494         workFolderPath = ""; | 
| jtkorhonen@0 | 1495     } | 
| jtkorhonen@0 | 1496 | 
| jtkorhonen@0 | 1497     QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint(); | 
| jtkorhonen@0 | 1498     QSize size = settings.value("size", QSize(400, 400)).toSize(); | 
| jtkorhonen@0 | 1499     firstStart = settings.value("firststart", QVariant(true)).toBool(); | 
| jtkorhonen@0 | 1500 | 
| Chris@109 | 1501 //!!!    initialFileTypesBits = (unsigned char) settings.value("viewFileTypes", QVariant(DEFAULT_HG_STAT_BITS)).toInt(); | 
| jtkorhonen@0 | 1502     resize(size); | 
| jtkorhonen@0 | 1503     move(pos); | 
| jtkorhonen@0 | 1504 } | 
| jtkorhonen@0 | 1505 | 
| jtkorhonen@17 | 1506 | 
| jtkorhonen@0 | 1507 void MainWindow::writeSettings() | 
| jtkorhonen@0 | 1508 { | 
| Chris@61 | 1509     QSettings settings; | 
| jtkorhonen@0 | 1510     settings.setValue("pos", pos()); | 
| jtkorhonen@0 | 1511     settings.setValue("size", size()); | 
| jtkorhonen@0 | 1512     settings.setValue("remoterepopath", remoteRepoPath); | 
| jtkorhonen@0 | 1513     settings.setValue("workfolderpath", workFolderPath); | 
| jtkorhonen@0 | 1514     settings.setValue("firststart", firstStart); | 
| Chris@98 | 1515     //!!!settings.setValue("viewFileTypes", hgTabs -> getFileTypesBits()); | 
| jtkorhonen@0 | 1516 } | 
| jtkorhonen@0 | 1517 | 
| jtkorhonen@0 | 1518 | 
| jtkorhonen@0 | 1519 | 
| jtkorhonen@0 | 1520 |