# # # delete "res/forms/main_window.ui" # # rename "doxygen.conf" # to "attic/doxygen.conf" # # rename "res/forms/about.ui" # to "res/forms/dialogs/about.ui" # # rename "res/forms/add_edit_attribute.ui" # to "res/forms/dialogs/add_edit_attribute.ui" # # rename "res/forms/add_edit_variables.ui" # to "res/forms/dialogs/add_edit_variables.ui" # # rename "res/forms/application_update.ui" # to "res/forms/dialogs/application_update.ui" # # rename "res/forms/changeset_browser.ui" # to "res/forms/dialogs/changeset_browser.ui" # # rename "res/forms/checkout_revision.ui" # to "res/forms/dialogs/checkout_revision.ui" # # rename "res/forms/commit_revision.ui" # to "res/forms/dialogs/commit_revision.ui" # # rename "res/forms/create_database.ui" # to "res/forms/dialogs/create_database.ui" # # rename "res/forms/db_variables.ui" # to "res/forms/panels/db_variables.ui" # # rename "res/forms/file_diff.ui" # to "res/forms/dialogs/file_diff.ui" # # rename "res/forms/file_history.ui" # to "res/forms/dialogs/file_history.ui" # # rename "res/forms/generate_keypair.ui" # to "res/forms/dialogs/generate_keypair.ui" # # rename "res/forms/icon_help.ui" # to "res/forms/panels/icon_help.ui" # # rename "res/forms/key_management.ui" # to "res/forms/dialogs/key_management.ui" # # rename "res/forms/manifest.ui" # to "res/forms/dialogs/manifest.ui" # # rename "res/forms/message.ui" # to "res/forms/dialogs/message.ui" # # rename "res/forms/nodeinfo.ui" # to "res/forms/panels/nodeinfo.ui" # # rename "res/forms/open_prompt.ui" # to "res/forms/dialogs/open_prompt.ui" # # rename "res/forms/preferences.ui" # to "res/forms/dialogs/preferences.ui" # # rename "res/forms/revision_diff.ui" # to "res/forms/dialogs/revision_diff.ui" # # rename "res/forms/select_revision.ui" # to "res/forms/dialogs/select_revision.ui" # # rename "res/forms/unaccounted_renames.ui" # to "res/forms/dialogs/unaccounted_renames.ui" # # rename "res/forms/update_workspace.ui" # to "res/forms/dialogs/update_workspace.ui" # # rename "src/view/AttributesView.cpp" # to "src/view/widgets/AttributesView.cpp" # # rename "src/view/AttributesView.h" # to "src/view/widgets/AttributesView.h" # # rename "src/view/ChangeLogEdit.cpp" # to "src/view/widgets/ChangeLogEdit.cpp" # # rename "src/view/ChangeLogEdit.h" # to "src/view/widgets/ChangeLogEdit.h" # # rename "src/view/ColorPicker.cpp" # to "src/view/widgets/ColorPicker.cpp" # # rename "src/view/ColorPicker.h" # to "src/view/widgets/ColorPicker.h" # # rename "src/view/DatabaseMenuBar.cpp" # to "src/view/widgets/DatabaseMenuBar.cpp" # # rename "src/view/DatabaseMenuBar.h" # to "src/view/widgets/DatabaseMenuBar.h" # # rename "src/view/DatabaseWindow.cpp" # to "src/view/mainwindows/DatabaseWindow.cpp" # # rename "src/view/DatabaseWindow.h" # to "src/view/mainwindows/DatabaseWindow.h" # # rename "src/view/DiffStatusView.cpp" # to "src/view/widgets/DiffStatusView.cpp" # # rename "src/view/DiffStatusView.h" # to "src/view/widgets/DiffStatusView.h" # # rename "src/view/InventoryView.cpp" # to "src/view/widgets/InventoryView.cpp" # # rename "src/view/InventoryView.h" # to "src/view/widgets/InventoryView.h" # # rename "src/view/InventoryViewDelegate.cpp" # to "src/view/widgets/InventoryViewDelegate.cpp" # # rename "src/view/InventoryViewDelegate.h" # to "src/view/widgets/InventoryViewDelegate.h" # # rename "src/view/MainWindow.cpp" # to "src/view/mainwindows/MainWindow.cpp" # # rename "src/view/MainWindow.h" # to "src/view/mainwindows/MainWindow.h" # # rename "src/view/MenuBar.cpp" # to "src/view/widgets/MenuBar.cpp" # # rename "src/view/MenuBar.h" # to "src/view/widgets/MenuBar.h" # # rename "src/view/Splitter.cpp" # to "src/view/widgets/Splitter.cpp" # # rename "src/view/Splitter.h" # to "src/view/widgets/Splitter.h" # # rename "src/view/ToolBox.cpp" # to "src/view/widgets/ToolBox.cpp" # # rename "src/view/ToolBox.h" # to "src/view/widgets/ToolBox.h" # # rename "src/view/TreeView.cpp" # to "src/view/widgets/TreeView.cpp" # # rename "src/view/TreeView.h" # to "src/view/widgets/TreeView.h" # # rename "src/view/WorkspaceMenuBar.cpp" # to "src/view/widgets/WorkspaceMenuBar.cpp" # # rename "src/view/WorkspaceMenuBar.h" # to "src/view/widgets/WorkspaceMenuBar.h" # # rename "src/view/WorkspaceWindow.cpp" # to "src/view/mainwindows/WorkspaceWindow.cpp" # # rename "src/view/WorkspaceWindow.h" # to "src/view/mainwindows/WorkspaceWindow.h" # # rename "tests" # to "attic/tests" # # add_dir "res/forms/dialogs" # # add_dir "res/forms/panels" # # add_dir "res/forms/widgets" # # add_dir "src/view/mainwindows" # # add_dir "src/view/widgets" # # add_file "attic/CheckableList.cpp" # content [3d06b965a4d1041f8f5c736deeaa1e9e69179ab6] # # add_file "attic/CheckableList.h" # content [0b6530ba31ddf437d9572763a7115605a3af32d5] # # add_file "attic/README" # content [ee24a56cb94e83ce81bd3e08ef3a5b2fa579b3f1] # # add_file "attic/WorkspaceAction.cpp" # content [e6a918afd4db05ee63853c5f4b62b639a0ba0b76] # # add_file "attic/WorkspaceAction.h" # content [41115965ebed18a46af40aab63db7c590ee846bc] # # add_file "attic/confirm_item_action.ui" # content [b65602806c513f3cba44490433d3dbf95659cb53] # # add_file "attic/fix_inventory_watcher_with_viewport_only_watching.diff" # content [d1618b314fa9af69c240375e54648fb7b8d3e157] # # add_file "attic/gitk_like_revision_graph.diff" # content [9e8ad385169c65e1f20ca363331c739871348169] # # add_file "attic/setup_our_own_crash_handler.diff" # content [8080efdeed449e7c33b19448b27c6bf6d99f5ec2] # # add_file "attic/workspace_action.ui" # content [b65602806c513f3cba44490433d3dbf95659cb53] # # add_file "attic/workspace_actions.diff" # content [3754ef144fb7e537994bca029226fc61a7d288b2] # # patch "guitone.pro" # from [9cd02c579fa277a37c575dd58a19cb0ec97aa712] # to [79353bf274a6e9053299903a86555ba623743f19] # # patch "res/forms/dialogs/file_diff.ui" # from [2bc8e89bcd40649e690c55899c588e156dd389d3] # to [e29bcef5bf07c2c37e9ac76a48c6ade00fbcdcba] # ============================================================ --- attic/CheckableList.cpp 3d06b965a4d1041f8f5c736deeaa1e9e69179ab6 +++ attic/CheckableList.cpp 3d06b965a4d1041f8f5c736deeaa1e9e69179ab6 @@ -0,0 +1,129 @@ +/*************************************************************************** + * Copyright (C) 2008 by Thomas Keller * + * address@hidden * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#include "CheckableList.h" + +CheckableList::CheckableList(QWidget * parent) + : QListView(parent), action(Addition), itemModel(0) +{ + itemModel = new QStandardItemModel(); + + setModel(itemModel); + + connect( + itemModel, SIGNAL(itemChanged(QStandardItem *)), + this, SLOT(itemChanged(QStandardItem *)) + ); +} + +CheckableList::~CheckableList() +{ + delete itemModel; +} + +void CheckableList::setItems(const QStringList & items) +{ + itemModel->clear(); + + QStringList sortedItems(items); + qSort(sortedItems); + + QStandardItem * modelItem; + foreach (const QString & item, sortedItems) + { + modelItem = new QStandardItem(item); + modelItem->setCheckable(true); + modelItem->setCheckState(Qt::Checked); + itemModel->appendRow(modelItem); + } +} + +void CheckableList::setAction(Action a) +{ + action = a; +} + +QStringList CheckableList::getCheckedItems() const +{ + QStandardItem * item; + QStringList items; + for (int i=0; i < itemModel->rowCount(); i++) + { + item = itemModel->item(i); + if (item->checkState() == Qt::Checked) + { + items.push_back(item->text()); + } + } + return items; +} + +// +// if a list item gets activated or deactivated, we might need to handle +// dependent items as well - see the following matrix: +// +// | Addition | Deletion +// | upwards | downwards | upwards | downwards +// ----------------------------------------------------------------- +// checked | checked | unchanged | unchanged | checked +// unchecked | unchanged | unchecked | unchecked | unchanged +// +void CheckableList::itemChanged(QStandardItem * changedItem) +{ + QList upperItems, lowerItems, tmpItems; + + QRegExp rx("[^\\/]+\\/?$"); + QString curPath = changedItem->text(); + while (true) + { + curPath = curPath.replace(rx, ""); + tmpItems = itemModel->findItems(curPath); + if (tmpItems.size() == 0) + break; + upperItems << tmpItems; + } + + lowerItems = itemModel->findItems(changedItem->text(), Qt::MatchStartsWith); + + Qt::CheckState checkState = changedItem->checkState(); + + // + // change the upper items + // + if ((action == Addition && checkState == Qt::Checked) || + (action == Deletion && checkState == Qt::Unchecked)) + { + foreach (QStandardItem * item, upperItems) + { + item->setCheckState(checkState); + } + } + + // + // now change the lower items + // + if ((action == Addition && checkState == Qt::Unchecked) || + (action == Deletion && checkState == Qt::Checked)) + { + foreach (QStandardItem * item, lowerItems) + { + item->setCheckState(checkState); + } + } +} + ============================================================ --- attic/CheckableList.h 0b6530ba31ddf437d9572763a7115605a3af32d5 +++ attic/CheckableList.h 0b6530ba31ddf437d9572763a7115605a3af32d5 @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2008 by Thomas Keller * + * address@hidden * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#ifndef CHECKABLE_LIST_H +#define CHECKABLE_LIST_H + +#include +#include + +class CheckableList : public QListView +{ + Q_OBJECT +public: + enum Action { Addition, Deletion } action; + CheckableList(QWidget *); + ~CheckableList(); + + void setItems(const QStringList &); + void setAction(Action); + QStringList getCheckedItems() const; + +private slots: + void itemChanged(QStandardItem *); + +private: + QStandardItemModel * itemModel; +}; + +#endif + ============================================================ --- attic/README ee24a56cb94e83ce81bd3e08ef3a5b2fa579b3f1 +++ attic/README ee24a56cb94e83ce81bd3e08ef3a5b2fa579b3f1 @@ -0,0 +1 @@ +This directory contain unsorted patches, tryouts and other stuff I didn't came around finishing. Some things might be solved otherwise in the meantime, other things might never get completed. This basically exists to prevent loosing any of the partial code or ideas. ============================================================ --- attic/WorkspaceAction.cpp e6a918afd4db05ee63853c5f4b62b639a0ba0b76 +++ attic/WorkspaceAction.cpp e6a918afd4db05ee63853c5f4b62b639a0ba0b76 @@ -0,0 +1,128 @@ +/*************************************************************************** + * Copyright (C) 2008 by Thomas Keller * + * address@hidden * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#include "WorkspaceAction.h" + +#include +#include + +WorkspaceAction::WorkspaceAction(QWidget * parent) + : Dialog(parent), invModel(0) +{ + setupUi(this); + Dialog::init(); + + QStyle * style = QApplication::style(); + QIcon standardIcon = style->standardIcon(QStyle::SP_MessageBoxQuestion, 0, this); + int iconSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize); + questionIcon->setPixmap(standardIcon.pixmap(iconSize)); +} + +WorkspaceAction::~WorkspaceAction() +{ + if (inventory) delete inventory; +} + +void WorkspaceAction::showAddableItems(const QStringList & items) +{ + action = Add; + itemList->setAction(CheckableList::Addition) + + setWindowTitle(tr("Confirm your selection")); + actionText->setText(tr("Please confirm the addition of the following items:")); + + populateItemsFromFilesystem(items); +} + +void WorkspaceAction::showRemovableItems(const QStringList & items) +{ + action = Remove; + itemList->setAction(CheckableList::Deletion); + + setWindowTitle(tr("Confirm your selection")); + actionText->setText(tr("Please confirm the deletion of the following items:")); + + populateItemsFromInventory(items); +} + +void WorkspaceAction::showRevertableItems(const QStringList & items) +{ + action = Revert; + // a revert has the same path restrictions like a removal, + // i.e. dependent sub-paths are reverted as well if a parent + // item should be reverted + itemList->setAction(CheckableList::Deletion); + + setWindowTitle(tr("Confirm your selection")); + actionText->setText(tr("Please confirm the reversal of the following items:")); + + populateItemsFromInventory(items); +} + +void WorkspaceAction::populateItemsFromFilesystem(const QStringList & items) +{ + populatedPaths.clear(); + foreach (const QString & item, items) + { + // FIXME: do something here + } +} + +void WorkspaceAction::populateItemsFromInventory(const QStringList & items) +{ + I(!workspacePath.isEmpty()); + pathsToPopulate = items; + populatedPaths.clear(); + + if (!inventory) + { + inventory = new Inventory(); + inventory->setWorkspacePath(workspacePath); + + connect( + inventory, SIGNAL(inventoryRead(const QString &)), + this, SLOT(inventoryRead(const QString &)) + ); + } + + inventory->read(pathsToPopulate.pop()); +} + +void WorkspaceAction::inventoryRead() +{ + if (action == Revert) + { + populatedPaths.unite(inventory->getRevertablePaths()); + } + else + if (action == Remove) + { + populatedPaths.unite(inventory->getRemovablePaths()); + } + else + I(false); + + if (pathsToPopulate.size() > 1) + { + inventory->read(pathsToPopulate.pop()); + return; + } + + itemList->setItems(populatedPaths.toList()); + populatedPaths.clear(); +} ============================================================ --- attic/WorkspaceAction.h 41115965ebed18a46af40aab63db7c590ee846bc +++ attic/WorkspaceAction.h 41115965ebed18a46af40aab63db7c590ee846bc @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2008 by Thomas Keller * + * address@hidden * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#ifndef WORKSPACE_ACTION_H +#define WORKSPACE_ACTION_H + +#include "ui_workspace_action.h" +#include "Dialog.h" + +class WorkspaceAction : public Dialog, private Ui::WorkspaceAction +{ + Q_OBJECT + +public: + WorkspaceAction(QWidget *); + ~WorkspaceAction(); + + void setWorkspacePath(WorkspacePath p) { workspacePath = p; } + +public slots: + void showAddableItems(const QStringList &); + void showRemovableItems(const QStringList &); + void showRevertableItems(const QStringList &); + +private slots: + void inventoryRead(const QString &); + +private: + void populateItemsForAction(Action, const QStringList &); + + WorkspacePath workspacePath; + Inventory * inventory; + + QStringList pathsToPopulate; + QSet populatedPaths; + enum Action { Add, Drop, Revert }; +}; + +#endif ============================================================ --- attic/confirm_item_action.ui b65602806c513f3cba44490433d3dbf95659cb53 +++ attic/confirm_item_action.ui b65602806c513f3cba44490433d3dbf95659cb53 @@ -0,0 +1,109 @@ + + WorkspaceAction + + + + 0 + 0 + 426 + 337 + + + + + + + true + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + TextLabel + + + true + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + CheckableList + QListView +
CheckableList.h
+
+
+ + + + buttonBox + accepted() + WorkspaceAction + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WorkspaceAction + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
============================================================ --- attic/fix_inventory_watcher_with_viewport_only_watching.diff d1618b314fa9af69c240375e54648fb7b8d3e157 +++ attic/fix_inventory_watcher_with_viewport_only_watching.diff d1618b314fa9af69c240375e54648fb7b8d3e157 @@ -0,0 +1,214 @@ +# +# old_revision [67c84df46a415fff5aad5ab3cb954c5c04cf9b90] +# +# patch "src/view/InventoryView.cpp" +# from [264358ef757142675513404c60332d0a881718fb] +# to [f2ed0d445d02b3bed7e186b542f6a31abdfdd93c] +# +# patch "src/view/InventoryView.h" +# from [43f47c2dd61433f5d526edc045cec2c8f7c26d67] +# to [f50d41d8e2c68d9f0e7a32f3889ada612587e05f] +# +============================================================ +--- src/view/InventoryView.cpp 264358ef757142675513404c60332d0a881718fb ++++ src/view/InventoryView.cpp f2ed0d445d02b3bed7e186b542f6a31abdfdd93c +@@ -45,6 +45,16 @@ InventoryView::InventoryView(QWidget * p + this, SIGNAL(contextMenuRequested(const QModelIndexList &, const QPoint &)), + this, SLOT(slotContextMenuRequested(const QModelIndexList &, const QPoint &)) + ); ++ ++ connect( ++ this, SIGNAL(addedToViewport(const QModelIndexList &)), ++ this, SLOT(addedIndexes(const QModelIndexList &)) ++ ); ++ ++ connect( ++ this, SIGNAL(removedFromViewport(const QModelIndexList &)), ++ this, SLOT(removedIndexes(const QModelIndexList &)) ++ ); + } + + void InventoryView::setType(Type t) +@@ -790,3 +800,143 @@ void InventoryView::setBackgroundImage() + "background-repeat: no-repeat;}"); + } + } ++ ++bool InventoryView::viewportEvent(QEvent * ev) ++{ ++ switch (ev->type()) ++ { ++ case QEvent::DragMove: ++ case QEvent::Wheel: ++ case QEvent::Resize: ++ // FIXME: we should also react on model / filter changes! ++ notifyAboutViewportChanges(); ++ default: ++ return QAbstractScrollArea::viewportEvent(ev); ++ } ++ I(false); ++} ++ ++void InventoryView::notifyAboutViewportChanges() ++{ ++ QModelIndex root = rootIndex(); ++ if (!root.isValid()) ++ { ++ // as long as the root index is invalid we should not have recorded ++ // any previous items... ++ //I(itemsVisibleInViewport.size() == 0); ++ return; ++ } ++ ++ QModelIndex startIndex = root.child(0, 0); ++ if (!startIndex.isValid()) ++ { ++ if (itemsVisibleInViewport.size() > 0) ++ { ++ emit removedFromViewport(itemsVisibleInViewport); ++ } ++ itemsVisibleInViewport.clear(); ++ return; ++ } ++ ++ if (itemsVisibleInViewport.size() > 0) ++ { ++ startIndex = itemsVisibleInViewport.at(0); ++ } ++ ++ int offset = verticalOffset(); ++ int maxOffset = offset + height(); ++ ++ int lastOffset = visualRect(startIndex).top(); ++ ++ // we have no optimization here whatsoever (binsearch), we just assume that ++ // whatever last visible top item was displayed, the new top item has to ++ // be somewhere near to it ++ QModelIndexList newIndexes; ++ QModelIndex tmpIndex = startIndex; ++ bool goUp = offset < lastOffset; ++ ++ while (true) ++ { ++ tmpIndex = goUp ? indexAbove(tmpIndex) : indexBelow(tmpIndex); ++ if (!tmpIndex.isValid()) break; ++D(QString("first round - item %1").arg(sourceItem(tmpIndex)->getLabel())); ++ QRect rc = visualRect(tmpIndex); ++ ++ if (rc.top() >= offset && rc.top() < maxOffset) ++ { ++ if (goUp) ++ newIndexes.prepend(tmpIndex); ++ else ++ newIndexes.append(tmpIndex); ++ } ++ ++ if (rc.top() <= offset && rc.bottom() > offset) ++ { ++ break; ++ } ++ } ++ ++ // now do the same in the other direction, ++ // this time we start with the first / last known new index ++ tmpIndex = goUp ? newIndexes.last() : newIndexes.first(); ++ ++ while (true) ++ { ++ tmpIndex = goUp ? indexBelow(tmpIndex) : indexAbove(tmpIndex); ++ if (!tmpIndex.isValid()) break; ++D(QString("second round - item %1").arg(sourceItem(tmpIndex)->getLabel())); ++ QRect rc = visualRect(tmpIndex); ++ ++ if (rc.top() >= offset && rc.top() < maxOffset) ++ { ++ if (goUp) ++ newIndexes.append(tmpIndex); ++ else ++ newIndexes.prepend(tmpIndex); ++ } ++ ++ if (rc.top() <= offset && rc.bottom() > offset) ++ { ++ break; ++ } ++ } ++ ++ QSet oldIndexSet = QSet::fromList(itemsVisibleInViewport); ++ QSet newIndexSet = QSet::fromList(newIndexes); ++ ++ QSet removedIndexes = oldIndexSet - newIndexSet; ++ if (removedIndexes.size() > 0) ++ { ++ emit removedFromViewport(removedIndexes.toList()); ++ } ++ ++ QSet addedIndexes = newIndexSet - oldIndexSet; ++ if (addedIndexes.size() > 0) ++ { ++ emit addedToViewport(addedIndexes.toList()); ++ } ++ ++ itemsVisibleInViewport = newIndexes; ++} ++ ++void InventoryView::addedIndexes(const QModelIndexList & indexes) ++{ ++ if (type != FileList) return; ++ D(QString("added %1, visible: %2").arg(indexes.size()).arg(itemsVisibleInViewport.size())); ++} ++ ++void InventoryView::removedIndexes(const QModelIndexList & indexes) ++{ ++ if (type != FileList) return; ++ D(QString("removed %1, visible: %2").arg(indexes.size()).arg(itemsVisibleInViewport.size())); ++} ++ ++ModelItem * InventoryView::sourceItem(const QModelIndex & idx) ++{ ++ QModelIndex source = ++ static_cast(idx.model())->mapToSource(idx); ++ I(source.isValid()); ++ ++ return static_cast(source.internalPointer()); ++} ++ +============================================================ +--- src/view/InventoryView.h 43f47c2dd61433f5d526edc045cec2c8f7c26d67 ++++ src/view/InventoryView.h f50d41d8e2c68d9f0e7a32f3889ada612587e05f +@@ -48,6 +48,8 @@ signals: + void diffFile(const QString &); + void fileHistory(const QString &); + void commitRevision(const QStringList &); ++ void addedToViewport(const QModelIndexList &); ++ void removedFromViewport(const QModelIndexList &); + + private: + enum DefaultAction { None, Chdir, Open, FileDiff, Commit }; +@@ -57,6 +59,9 @@ private: + DefaultAction getDefaultAction(const QModelIndex &) const; + void createAndConnectContextActions(); + void closeEvent(); ++ bool viewportEvent(QEvent *); ++ void notifyAboutViewportChanges(); ++ ModelItem * sourceItem(const QModelIndex &); + + QAction * actChdir; + QAction * actOpen; +@@ -81,6 +86,7 @@ private: + Type type; + + InventoryViewDelegate invViewDelegate; ++ QModelIndexList itemsVisibleInViewport; + + private slots: + void newNodeLoaded(const QModelIndex &, const QModelIndex &); +@@ -89,6 +95,8 @@ private slots: + void itemClicked(const QModelIndex & index); + void itemDoubleClicked(const QModelIndex & index); + void setBackgroundImage(); ++ void addedIndexes(const QModelIndexList &); ++ void removedIndexes(const QModelIndexList &); + + void slotChdir(); + void slotOpen(); ============================================================ --- attic/gitk_like_revision_graph.diff 9e8ad385169c65e1f20ca363331c739871348169 +++ attic/gitk_like_revision_graph.diff 9e8ad385169c65e1f20ca363331c739871348169 @@ -0,0 +1,550 @@ +# +# old_revision [debda74fdcb8662d9b15c341f526d02f3f04a7de] +# +# patch "src/model/Graph.cpp" +# from [fa58d4e3fd6ebe3f1beb05a9682b7efced6ffed1] +# to [de409cbc2052111b05e1f96b534636c285850872] +# +# patch "src/model/Graph.h" +# from [12331956dd8457649a45dbfe59f4f10b48676d9d] +# to [d42d7472337808bacdaa2c0341458e138c91668a] +# +============================================================ +--- src/model/Graph.cpp fa58d4e3fd6ebe3f1beb05a9682b7efced6ffed1 ++++ src/model/Graph.cpp de409cbc2052111b05e1f96b534636c285850872 +@@ -30,12 +30,23 @@ void Graph::readGraph() + ); + } + +-void Graph::filterBranch(const QString & branch) ++void Graph::filterGraphByBranch(const QString & branch) + { ++ if (branchHeads.contains(branch)) ++ { ++ buildLanes(branch, branchHeads.value(branch)); ++ return; ++ } ++ + AutomateCommand::enqueueDatabaseTask( +- databaseFile, +- MonotoneTask(QStringList() << "select" << "b:"+branch) +- ); ++ databaseFile, ++ MonotoneTask(QStringList() << "select" << "b:"+branch) ++ ); ++ ++ AutomateCommand::enqueueDatabaseTask( ++ databaseFile, ++ MonotoneTask(QStringList() << "heads" << branch) ++ ); + } + + void Graph::processTaskResult(const MonotoneTask & task) +@@ -91,33 +102,41 @@ void Graph::processTaskResult(const Mono + I(revisionMap.contains(rev)); + revisionMap[rev]->branches.append(branch); + } +- +- currentBranch = branch; +- +- AutomateCommand::enqueueDatabaseTask( +- databaseFile, +- QStringList() << "heads" << branch +- ); + return; + } + + if (cmd == "heads") + { + QString branch = QString(task.getArguments().at(1)); +- QStringList heads = output.split("\n", QString::SkipEmptyParts); ++ const QStringList heads = output.split("\n", QString::SkipEmptyParts); + + branchHeads.insert(branch, heads); +- buildLanes(heads, QStringList()); ++ buildLanes(branch, heads); + return; + } + } + +-void Graph::buildLanes(QStringList & newRevisions, const QStringList & lastRevisions) ++void Graph::buildLanes(const QString & branch, const QStringList & heads) + { ++ revisionOrder = QStringList(); ++ QStringList startRevisions(heads); ++ buildLanes(branch, startRevisions, QStringList()); ++} ++ ++void Graph::buildLanes(const QString & branch, QStringList & newRevisions, const QStringList & lastRevisions) ++{ + QString rev = newRevisions.takeFirst(); ++ revisionOrder.push_back(rev); + QStringList nextRevisions = lastRevisions; + +- QList lanes; ++ QList lanes; ++ QList lastLanes; ++ ++ if (!revisionOrder.isEmpty()) ++ { ++ lastLanes = revisionMap[revisionOrder.last()]->lanes; ++ } ++ + bool removedDeadLine = false; + + // initialize all lanes with plain vertical bars first; +@@ -125,8 +144,17 @@ void Graph::buildLanes(QStringList & new + // their slot for the next revision(s) - but only one lane per row + for (int i=0; ibranches.contains(branch)) + { ++ continue; ++ } ++ ++ if (rev.isEmpty() && !removedDeadLine) ++ { + nextRevisions.removeAt(i); + I(i > 0); + i--; +@@ -135,30 +163,73 @@ void Graph::buildLanes(QStringList & new + } + + // preserve further dead lines +- if (nextRevisions.at(i).isEmpty()) ++ if (rev.isEmpty()) + { +- lanes.push_back(Revision::Empty); ++ lanes.push_back(Empty); + } + else + { +- lanes.push_back(removedDeadLine ? Revision::BarToLeft +- : Revision::Bar); ++ I(lastLanes.size() > lanes.size()); ++ LaneType lastType = lastLanes.at(lanes.size()); ++ ++ if (isBrokenType(lastType)) ++ { ++ lanes.push_back(removedDeadLine ? BarToLeftBroken : BarBroken); ++ } ++ else ++ { ++ lanes.push_back(removedDeadLine ? BarToLeft : Bar); ++ } + } + } + +- I(lanes.size() == nextRevisions.size()); ++ I(lanes.size() <= nextRevisions.size()); + + Revision * revObj = revisionMap.value(rev); + int idx = lastRevisions.indexOf(rev); + + if (idx == -1) + { +- Revision::LaneType type; ++ LaneType type; + switch (revObj->parents.size()) + { +- case 0: type = Revision::SingleNode; break; +- case 1: type = Revision::Head; break; +- case 2: type = Revision::HeadMerge; break; ++ case 0: type = SingleNode; break; ++ case 1: ++ Revision * parent = revisionMap.value(revObj->parents.at(0)); ++ if (parent->branches.contains(branch)) ++ { ++ type = Head; ++ } ++ else ++ { ++ type = HeadBroken; ++ } ++ break; ++ case 2: ++ Revision * parent1 = revisionMap.value(revObj->parents.at(0)); ++ Revision * parent2 = revisionMap.value(revObj->parents.at(1)); ++ if (parent1->branches.contains(branch) && ++ parent2->branches.contains(branch)) ++ { ++ type = HeadMerge; ++ } ++ else ++ if (!parent1->branches.contains(branch) && ++ parent2->branches.contains(branch)) ++ { ++ type = HeadMergeBrokenParentLeft; ++ } ++ else ++ if (parent1->branches.contains(branch) && ++ !parent2->branches.contains(branch)) ++ { ++ type = HeadMergeBrokenParentRight; ++ } ++ else ++ { ++ type = HeadMergeBroken; ++ } ++ break; + default: I(false); + } + nextRevisions += revObj->parents; +@@ -169,21 +240,21 @@ void Graph::buildLanes(QStringList & new + // add revisions for the next round + newRevisions += revObj->parents; + +- Revision::LaneType type, defaultNextType; ++ LaneType type, defaultNextType; + switch (revObj->parents.size()) + { + case 0: +- type = Revision::Tail; +- defaultNextType = Revision::BarToLeft; ++ type = Tail; ++ defaultNextType = BarToLeft; + nextRevisions.replace(idx, QString()); + break; + case 1: +- type = Revision::Node; +- defaultNextType = Revision::Bar; ++ type = Node; ++ defaultNextType = Bar; + nextRevisions.replace(idx, revObj->parents.at(0)); + break; + case 2: +- type = Revision::Merge; ++ type = Merge; + nextRevisions.replace(idx, revObj->parents.at(0)); + + // check the special case where a dead line is right +@@ -192,12 +263,12 @@ void Graph::buildLanes(QStringList & new + if (idx + 1 < nextRevisions.size() && + nextRevisions.at(idx + 1).isEmpty()) + { +- defaultNextType = Revision::Bar; ++ defaultNextType = Bar; + nextRevisions.replace(idx + 1, revObj->parents.at(1)); + } + else + { +- defaultNextType = Revision::BarToRight; ++ defaultNextType = BarToRight; + nextRevisions.insert(idx + 1, revObj->parents.at(1)); + } + break; +@@ -212,14 +283,14 @@ void Graph::buildLanes(QStringList & new + { + switch (defaultNextType) + { +- case Revision::BarToLeft: +- defaultNextType = Revision::BarToLeftCrossing; ++ case BarToLeft: ++ defaultNextType = BarToLeftCrossing; + break; +- case Revision::Bar: +- defaultNextType = Revision::Crossing; ++ case Bar: ++ defaultNextType = Crossing; + break; +- case Revision::BarToRight: +- defaultNextType = Revision::BarToRightCrossing; ++ case BarToRight: ++ defaultNextType = BarToRightCrossing; + break; + default: I(false); + } +@@ -227,11 +298,11 @@ void Graph::buildLanes(QStringList & new + // do we join the line to a previous fork line? + if (!hasFork) + { +- lanes[i] = Revision::BarToFork; ++ lanes[i] = BarToFork; + } + else + { +- lanes[i] = Revision::BarToForkJoin; ++ lanes[i] = BarToForkJoin; + } + + // mark this line as not being continued +@@ -250,9 +321,9 @@ void Graph::buildLanes(QStringList & new + { + switch (type) + { +- case Revision::Tail: type = Revision::TailFork; break; +- case Revision::Node: type = Revision::Fork; break; +- case Revision::Merge: type = Revision::MergeFork; break; ++ case Tail: type = TailFork; break; ++ case Node: type = Fork; break; ++ case Merge: type = MergeFork; break; + default: I(false); + } + } +@@ -265,11 +336,11 @@ void Graph::buildLanes(QStringList & new + if (newRevisions.size() == 0) + { + // FIXME: next thing is to draw the mess +- emit lanesCreated(); ++ emit lanesCreated(branch); + return; + } + + // recursion +- buildLanes(newRevisions, nextRevisions); ++ buildLanes(branch, newRevisions, nextRevisions); + } + +============================================================ +--- src/model/Graph.h 12331956dd8457649a45dbfe59f4f10b48676d9d ++++ src/model/Graph.h d42d7472337808bacdaa2c0341458e138c91668a +@@ -22,6 +22,155 @@ + #include "AutomateCommand.h" + #include "vocab.h" + ++/** ++ * possible lane types - the *Broken parts denote the same line type ++ * with a different line style (¦ instead of |) which means that ++ * revision on this line do not have the filtered branch cert attached ++ * Any node whose parents and childs are not on the current branch are ++ * completly invisible and are not rendered. ++ */ ++ ++enum LaneType { Empty, /* ( ) */ ++ Bar, ++ BarBroken, ++ /* | ++ | ++ | */ ++ Crossing, ++ CrossingBroken, ++ /* | ++ -^- ++ | */ ++ BarToLeft, ++ BarToLeftBroken, ++ /* | ++ / ++ | */ ++ BarToRight, ++ BarToRightBroken, ++ /* | ++ \ ++ | */ ++ BarToLeftCrossing, ++ BarToLeftCrossingBroken, ++ /* | ++ -^-- ++ | */ ++ BarToRightCrossing, ++ BarToRightCrossingBroken, ++ /* | ++ --^- ++ | */ ++ BarToFork, ++ BarToForkBroken, ++ /* | ++ _/ ++ */ ++ BarToForkJoin, ++ BarToForkJoinBroken, ++ /* | ++ _/-- ++ */ ++ SingleNode, /* ++ o ++ */ ++ Node, ++ NodeBrokenChild, ++ NodeBrokenParent, /* | ++ o ++ | */ ++ Fork, ++ // we cannot render a particular child other than the child ++ // of the current line as "broken line" here because a ++ // revision could have multiple children, of which ++ // 0 or more children are not on the same branch, ++ // so this particular rendering has to be done in the ++ // particular line of the not-on-branch revision ++ ForkBrokenChild, ++ ForkBrokenParent, /* | ++ o- ++ | */ ++ Merge, ++ MergeBrokenChild, ++ MergeBrokenParentLeft, ++ MergeBrokenParentRight, ++ MergeBrokenChildParentLeft, ++ MergeBrokenChildParentRight, ++ /* | ++ o ++ |\ */ ++ MergeFork, ++ MergeForkBrokenChild, ++ MergeForkBrokenParentLeft, ++ MergeForkBrokenParentRight, ++ MergeForkBrokenChildParentLeft, ++ MergeForkBrokenChildParentRight, ++ /* | ++ o- ++ |\ */ ++ Head, ++ HeadBroken, ++ /* ++ o ++ | */ ++ HeadMerge, ++ HeadMergeBroken, ++ HeadMergeBrokenParentLeft, ++ HeadMergeBrokenParentRight, ++ /* ++ o ++ |\ */ ++ Tail, ++ TailBroken, ++ /* | ++ o ++ */ ++ TailFork, ++ TailForkBroken, ++ /* | ++ o- ++ */ ++}; ++ ++static bool isBrokenType(LaneType lane) ++{ ++ switch (lane) ++ { ++ case BarBroken: ++ case CrossingBroken: ++ case BarToLeftBroken: ++ case BarToRightBroken: ++ case BarToLeftCrossingBroken: ++ case BarToRightCrossingBroken: ++ case BarToForkBroken: ++ case BarToForkJoinBroken: ++ case NodeBrokenChild: ++ case NodeBrokenParent: ++ case ForkBrokenChild: ++ case ForkBrokenParent: ++ case MergeBrokenChild: ++ case MergeBrokenParentLeft: ++ case MergeBrokenParentRight: ++ case MergeBrokenChildParentLeft: ++ case MergeBrokenChildParentRight: ++ case MergeForkBrokenChild: ++ case MergeForkBrokenParentLeft: ++ case MergeForkBrokenParentRight: ++ case MergeForkBrokenChildParentLeft: ++ case MergeForkBrokenChildParentRight: ++ case HeadBroken: ++ case HeadMergeBroken: ++ case HeadMergeBrokenParentLeft: ++ case HeadMergeBrokenParentRight: ++ case TailBroken: ++ case TailForkBroken: ++ return true; ++ default: ++ return false; ++ } ++ I(false); ++} ++ + class Revision + { + public: +@@ -29,64 +178,6 @@ public: + QStringList parents; + QStringList children; + QStringList branches; +- +- /** +- * possible lane typess +- */ +- enum LaneType { Empty, /* ( ) */ +- Bar, /* | +- | +- | */ +- Crossing, /* | +- -^- +- | */ +- BarToLeft, /* | +- / +- | */ +- BarToRight, /* | +- \ +- | */ +- BarToLeftCrossing, /* | +- -^-- +- | */ +- BarToRightCrossing, /* | +- --^- +- | */ +- BarToFork, /* | +- _/ +- */ +- BarToForkJoin, /* | +- _/-- +- */ +- SingleNode, /* +- o +- */ +- Node, /* | +- o +- | */ +- Fork, /* | +- o- +- | */ +- Merge, /* | +- o +- |\ */ +- MergeFork, /* | +- o- +- |\ */ +- Head, /* +- o +- | */ +- HeadMerge, /* +- o +- |\ */ +- Tail, /* | +- o +- */ +- TailFork, /* | +- o- +- */ +- }; +- + QList lanes; + }; + +@@ -98,18 +189,19 @@ public: + + void readGraph(); + +- void filterBranch(const QString &); ++ void filterGraphByBranch(const QString &); + + signals: +- void lanesCreated(); ++ void lanesCreated(const QString &); + + private: + void processTaskResult(const MonotoneTask &); +- void buildLanes(QStringList &, const QStringList &); ++ void buildLanes(const QString &, const QStringList &); ++ void buildLanes(const QString &, QStringList &, const QStringList &); + + QMap revisionMap; + QMap branchHeads; +- QString currentBranch; ++ QStringList revisionOrder; + DatabaseFile databaseFile; + }; + ============================================================ --- attic/setup_our_own_crash_handler.diff 8080efdeed449e7c33b19448b27c6bf6d99f5ec2 +++ attic/setup_our_own_crash_handler.diff 8080efdeed449e7c33b19448b27c6bf6d99f5ec2 @@ -0,0 +1,119 @@ +# +# old_revision [5bcedd44c6818a9823c2c5e91703d4560cb033a2] +# +# patch "src/util/Platform.cpp" +# from [2c86bf985ac1f54de537bed0321530d9e55c83c0] +# to [930a98b2dd3941dd99330aadf6004efbb9ce6b55] +# +# patch "src/util/Platform.h" +# from [7f8f1005a264dc6ab04856b6ff944d59897486eb] +# to [377fb0c6ba0543286e143e3e09f6256d4c33d7cd] +# +============================================================ +--- src/util/Platform.cpp 2c86bf985ac1f54de537bed0321530d9e55c83c0 ++++ src/util/Platform.cpp 930a98b2dd3941dd99330aadf6004efbb9ce6b55 +@@ -25,14 +25,14 @@ + #include + #include + +-#ifdef Q_WS_WIN ++#ifdef Q_OS_WIN + #include + #include + #endif + +-#ifdef Q_WS_X11 ++#ifdef Q_OS_UNIX + #include +-using namespace std; ++#include + #endif + + // +@@ -193,7 +193,7 @@ QString Platform::getUsername() + { + QString username; + +-#ifdef Q_WS_WIN ++#ifdef Q_OS_WIN + #if defined(UNICODE) + if (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) + { +@@ -211,20 +211,56 @@ QString Platform::getUsername() + } + #endif + +-#ifdef Q_WS_X11 +-#define IS_UNIX ++#ifdef Q_OS_UNIX ++ username = QString::fromAscii(getenv("USER")); + #endif + +-#ifdef Q_WS_MACX +-#define IS_UNIX +-#endif ++ D(QString("Found username %1").arg(username)); + +-#ifdef IS_UNIX +- username = QString::fromAscii(getenv("USER")); ++ return username; ++} ++ ++#ifdef Q_OS_UNIX ++static void crash_handler(int signo) ++{ ++ char * argv[4]; ++ argv[0] = "open"; ++ argv[1] = "-a"; ++ argv[2] = "guitone.app"; ++ argv[3] = NULL; ++ ++ pid_t child_pid = fork(); ++ if (child_pid == 0) ++ { ++ execvp(argv[0], argv); ++ // If execvp returns, it must have failed ++ const char * err = "execution failed"; ++ write(2, err, strlen(err)); ++ _exit(1); ++ } ++ _exit(1); ++} ++// stolen from the monotone project, unix/main.cc ++static const int crash_signals[] = { ++ SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGBUS, SIGSYS, SIGTRAP ++}; ++#define crash_signals_len (sizeof crash_signals / sizeof crash_signals[0]) + #endif + +- D(QString("Found username %1").arg(username)); ++void Platform::setupCrashHandler() ++{ ++#ifdef Q_OS_UNIX ++ struct sigaction crash_handler_action; ++ size_t i; + +- return username; ++ crash_handler_action.sa_flags = SA_RESETHAND; ++ crash_handler_action.sa_handler = &crash_handler; ++ sigemptyset(&crash_handler_action.sa_mask); ++ for (i = 0; i < crash_signals_len; i++) ++ { ++ sigaddset(&crash_handler_action.sa_mask, crash_signals[i]); ++ sigaction(crash_signals[i], &crash_handler_action, 0); ++ } ++#endif + } + +============================================================ +--- src/util/Platform.h 7f8f1005a264dc6ab04856b6ff944d59897486eb ++++ src/util/Platform.h 377fb0c6ba0543286e143e3e09f6256d4c33d7cd +@@ -33,6 +33,8 @@ public: + * Returns the name of the currently logged in user of the system + */ + static QString getUsername(); ++ ++ static void setupCrashHandler(); + }; + + #endif ============================================================ --- attic/workspace_action.ui b65602806c513f3cba44490433d3dbf95659cb53 +++ attic/workspace_action.ui b65602806c513f3cba44490433d3dbf95659cb53 @@ -0,0 +1,109 @@ + + WorkspaceAction + + + + 0 + 0 + 426 + 337 + + + + + + + true + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + TextLabel + + + true + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + CheckableList + QListView +
CheckableList.h
+
+
+ + + + buttonBox + accepted() + WorkspaceAction + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + WorkspaceAction + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
============================================================ --- attic/workspace_actions.diff 3754ef144fb7e537994bca029226fc61a7d288b2 +++ attic/workspace_actions.diff 3754ef144fb7e537994bca029226fc61a7d288b2 @@ -0,0 +1,196 @@ +# +# old_revision [8327e8dc51a166fba34f226aeb161c77b0ee36c9] +# +# patch "guitone.pro" +# from [54b9d7d520973b9d1d6be0a13b0e5c228e985a01] +# to [482d16fb4801f5fe42dd342e480deee8b1cc6596] +# +# patch "src/model/Inventory.cpp" +# from [7056e6451d09ab9dbb5793d2b9529a5fddff9420] +# to [5c51716fd34e1f7613eff169250993a5144097fc] +# +# patch "src/model/Inventory.h" +# from [c9663f40bd61cac606d5f3015c76fd78e8914fa6] +# to [100a6f18943a4b08e64ef75eb9fe955abf94412f] +# +# patch "src/view/InventoryView.cpp" +# from [459a7ffa747b6a863200677a97ae897fbc808ede] +# to [78dba7c8106680fa680c96c7e55b885a7504ce8d] +# +============================================================ +--- guitone.pro 54b9d7d520973b9d1d6be0a13b0e5c228e985a01 ++++ guitone.pro 482d16fb4801f5fe42dd342e480deee8b1cc6596 +@@ -38,6 +38,7 @@ HEADERS = src/view/TreeView.h \ + src/view/MainWindow.h \ + src/view/WorkspaceWindow.h \ + src/view/DatabaseWindow.h \ ++ src/view/CheckableList.h \ + src/view/dialogs/Dialog.h \ + src/view/dialogs/DialogManager.h \ + src/view/dialogs/WorkspaceDialogManager.h \ +@@ -60,6 +61,7 @@ HEADERS = src/view/TreeView.h \ + src/view/dialogs/OpenPrompt.h \ + src/view/dialogs/AddEditDatabaseVariable.h \ + src/view/dialogs/CreateDatabase.h \ ++ src/view/dialogs/WorkspaceAction.h \ + src/view/panels/IconHelp.h \ + src/view/panels/DatabaseVariables.h \ + src/view/panels/NodeInfo.h \ +@@ -120,6 +122,7 @@ SOURCES += src/view/TreeView.cpp \ + src/view/MainWindow.cpp \ + src/view/WorkspaceWindow.cpp \ + src/view/DatabaseWindow.cpp \ ++ src/view/CheckableList.cpp \ + src/view/dialogs/Dialog.cpp \ + src/view/dialogs/DialogManager.cpp \ + src/view/dialogs/WorkspaceDialogManager.cpp \ +@@ -142,6 +145,7 @@ SOURCES += src/view/TreeView.cpp \ + src/view/dialogs/OpenPrompt.cpp \ + src/view/dialogs/AddEditDatabaseVariable.cpp \ + src/view/dialogs/CreateDatabase.cpp \ ++ src/view/dialogs/WorkspaceAction.cpp \ + src/view/panels/IconHelp.cpp \ + src/view/panels/DatabaseVariables.cpp \ + src/view/panels/NodeInfo.cpp \ +@@ -211,7 +215,8 @@ FORMS += res/forms/select_revision.ui + res/forms/db_variables.ui \ + res/forms/add_edit_variables.ui \ + res/forms/nodeinfo.ui \ +- res/forms/create_database.ui ++ res/forms/create_database.ui \ ++ res/forms/workspace_action.ui + + UI_DIR = tmp + OBJECTS_DIR = tmp +============================================================ +--- src/model/Inventory.cpp 7056e6451d09ab9dbb5793d2b9529a5fddff9420 ++++ src/model/Inventory.cpp 5c51716fd34e1f7613eff169250993a5144097fc +@@ -324,6 +324,32 @@ QMap Inventory + return unaccountedRenames; + } + ++QSet Inventory::getRevertablePaths() const ++{ ++ QSet paths; ++ QMapIterator i(itemMap); ++ while (i.hasNext()) ++ { ++ i.next(); ++ if (!i.value()->hasChanged()) continue; ++ paths.insert(i.key()); ++ } ++ return paths; ++} ++ ++QSet Inventory::getRemovablePaths() const ++{ ++ QSet paths; ++ QMapIterator i(itemMap); ++ while (i.hasNext()) ++ { ++ i.next(); ++ if (!i.value()->isTracked()) continue; ++ paths.insert(i.key()); ++ } ++ return paths; ++} ++ + void Inventory::insertRowsRecursive(ModelItem * parentItem, const QMap > & parentChildRelations) + { + I(parentItem); +============================================================ +--- src/model/Inventory.h c9663f40bd61cac606d5f3015c76fd78e8914fa6 ++++ src/model/Inventory.h 100a6f18943a4b08e64ef75eb9fe955abf94412f +@@ -35,6 +35,9 @@ public: + ~Inventory(); + + QMap findUnaccountedRenames() const; ++ QSet getRevertablePaths() const; ++ QSet getRemovablePaths() const; ++ + static const int QueryLevel; + + public slots: +============================================================ +--- src/view/InventoryView.cpp 459a7ffa747b6a863200677a97ae897fbc808ede ++++ src/view/InventoryView.cpp 78dba7c8106680fa680c96c7e55b885a7504ce8d +@@ -19,6 +19,7 @@ + #include "InventoryView.h" + #include "Settings.h" + #include "InventoryItem.h" ++#include "ConfirmItemAction.h" + #include "vocab.h" + + #include +@@ -597,9 +598,26 @@ void InventoryView::slotAdd() + { + path = "."; + } ++ ++ // mark directories with a trailing slash ++ if (invitem->getFSType() == InventoryItem::Directory) ++ { ++ path.append("/"); ++ } ++ + paths.push_back(path); + } + ++ ConfirmItemAction dlg(this, ++ ConfirmItemAction::Add, ++ tr("Confirm file deletion"), ++ tr("The following files have been changeed since " ++ "last commit. If you drop them, their changes " ++ "will be lost."), ++ paths ++ ); ++ dlg.exec(); ++ + if (paths.size() == 0) + { + QMessageBox::information( +@@ -620,6 +638,8 @@ void InventoryView::slotRemove() + if (items.size() == 0) return; + + QStringList paths; ++ QStringList patchedFiles; ++ + foreach (const ModelItem * item, items) + { + const InventoryItem * invitem = dynamic_cast(item); +@@ -653,6 +673,18 @@ void InventoryView::slotRemove() + ); + return; + } ++ ++ if (invitem->hasStatus(InventoryItem::ContentsChanged)) ++ { ++ patchedFiles.push_back(path); ++ } ++ ++ // mark directories with a trailing slash ++ if (invitem->getNewType() == InventoryItem::Directory) ++ { ++ path.append("/"); ++ } ++ + paths.push_back(path); + } + +@@ -667,6 +699,16 @@ void InventoryView::slotRemove() + return; + } + ++ ConfirmItemAction dlg(this, ++ ConfirmItemAction::Drop, ++ tr("Confirm file deletion"), ++ tr("The following files have been changeed since " ++ "last commit. If you drop them, their changes " ++ "will be lost."), ++ paths ++ ); ++ dlg.exec(); ++ + emit dropPaths(paths); + } + ============================================================ --- guitone.pro 9cd02c579fa277a37c575dd58a19cb0ec97aa712 +++ guitone.pro 79353bf274a6e9053299903a86555ba623743f19 @@ -19,27 +19,28 @@ INCLUDEPATH = src/ \ QT += xml network } INCLUDEPATH = src/ \ - src/view \ + src/view/widgets \ + src/view/mainwindows \ src/view/dialogs \ src/view/panels \ src/model \ src/monotone \ src/util -HEADERS = src/view/TreeView.h \ - src/view/Splitter.h \ - src/view/InventoryView.h \ - src/view/InventoryViewDelegate.h \ - src/view/AttributesView.h \ - src/view/DiffStatusView.h \ - src/view/ChangeLogEdit.h \ - src/view/ColorPicker.h \ - src/view/MenuBar.h \ - src/view/DatabaseMenuBar.h \ - src/view/WorkspaceMenuBar.h \ - src/view/MainWindow.h \ - src/view/WorkspaceWindow.h \ - src/view/DatabaseWindow.h \ - src/view/ToolBox.h \ +HEADERS = src/view/widgets/TreeView.h \ + src/view/widgets/Splitter.h \ + src/view/widgets/InventoryView.h \ + src/view/widgets/InventoryViewDelegate.h \ + src/view/widgets/AttributesView.h \ + src/view/widgets/DiffStatusView.h \ + src/view/widgets/ChangeLogEdit.h \ + src/view/widgets/ColorPicker.h \ + src/view/widgets/MenuBar.h \ + src/view/widgets/DatabaseMenuBar.h \ + src/view/widgets/WorkspaceMenuBar.h \ + src/view/widgets/ToolBox.h \ + src/view/mainwindows/MainWindow.h \ + src/view/mainwindows/WorkspaceWindow.h \ + src/view/mainwindows/DatabaseWindow.h \ src/view/dialogs/Dialog.h \ src/view/dialogs/DialogManager.h \ src/view/dialogs/WorkspaceDialogManager.h \ @@ -109,21 +110,21 @@ HEADERS = src/view/TreeView.h \ src/GuitoneStandalone.h \ src/GuitoneDriver.h \ src/vocab.h -SOURCES += src/view/TreeView.cpp \ - src/view/Splitter.cpp \ - src/view/InventoryView.cpp \ - src/view/InventoryViewDelegate.cpp \ - src/view/AttributesView.cpp \ - src/view/DiffStatusView.cpp \ - src/view/ChangeLogEdit.cpp \ - src/view/ColorPicker.cpp \ - src/view/MenuBar.cpp \ - src/view/DatabaseMenuBar.cpp \ - src/view/WorkspaceMenuBar.cpp \ - src/view/MainWindow.cpp \ - src/view/WorkspaceWindow.cpp \ - src/view/DatabaseWindow.cpp \ - src/view/ToolBox.cpp \ +SOURCES += src/view/widgets/TreeView.cpp \ + src/view/widgets/Splitter.cpp \ + src/view/widgets/InventoryView.cpp \ + src/view/widgets/InventoryViewDelegate.cpp \ + src/view/widgets/AttributesView.cpp \ + src/view/widgets/DiffStatusView.cpp \ + src/view/widgets/ChangeLogEdit.cpp \ + src/view/widgets/ColorPicker.cpp \ + src/view/widgets/MenuBar.cpp \ + src/view/widgets/DatabaseMenuBar.cpp \ + src/view/widgets/WorkspaceMenuBar.cpp \ + src/view/widgets/ToolBox.cpp \ + src/view/mainwindows/MainWindow.cpp \ + src/view/mainwindows/WorkspaceWindow.cpp \ + src/view/mainwindows/DatabaseWindow.cpp \ src/view/dialogs/Dialog.cpp \ src/view/dialogs/DialogManager.cpp \ src/view/dialogs/WorkspaceDialogManager.cpp \ @@ -194,30 +195,29 @@ SOURCES += src/view/TreeView.cpp \ src/GuitoneDriver.cpp \ src/main.cpp -FORMS += res/forms/select_revision.ui \ - res/forms/update_workspace.ui \ - res/forms/checkout_revision.ui \ - res/forms/preferences.ui \ - res/forms/file_diff.ui \ - res/forms/revision_diff.ui \ - res/forms/key_management.ui \ - res/forms/generate_keypair.ui \ - res/forms/about.ui \ - res/forms/main_window.ui \ - res/forms/changeset_browser.ui \ - res/forms/manifest.ui \ - res/forms/commit_revision.ui \ - res/forms/application_update.ui \ - res/forms/file_history.ui \ - res/forms/unaccounted_renames.ui \ - res/forms/add_edit_attribute.ui \ - res/forms/open_prompt.ui \ - res/forms/icon_help.ui \ - res/forms/db_variables.ui \ - res/forms/add_edit_variables.ui \ - res/forms/nodeinfo.ui \ - res/forms/create_database.ui \ - res/forms/message.ui +FORMS += res/forms/dialogs/select_revision.ui \ + res/forms/dialogs/update_workspace.ui \ + res/forms/dialogs/checkout_revision.ui \ + res/forms/dialogs/preferences.ui \ + res/forms/dialogs/file_diff.ui \ + res/forms/dialogs/revision_diff.ui \ + res/forms/dialogs/key_management.ui \ + res/forms/dialogs/generate_keypair.ui \ + res/forms/dialogs/about.ui \ + res/forms/dialogs/changeset_browser.ui \ + res/forms/dialogs/manifest.ui \ + res/forms/dialogs/commit_revision.ui \ + res/forms/dialogs/application_update.ui \ + res/forms/dialogs/file_history.ui \ + res/forms/dialogs/unaccounted_renames.ui \ + res/forms/dialogs/add_edit_attribute.ui \ + res/forms/dialogs/open_prompt.ui \ + res/forms/dialogs/message.ui \ + res/forms/dialogs/add_edit_variables.ui \ + res/forms/dialogs/create_database.ui \ + res/forms/panels/icon_help.ui \ + res/forms/panels/db_variables.ui \ + res/forms/panels/nodeinfo.ui UI_DIR = tmp OBJECTS_DIR = tmp ============================================================ --- res/forms/file_diff.ui 2bc8e89bcd40649e690c55899c588e156dd389d3 +++ res/forms/dialogs/file_diff.ui e29bcef5bf07c2c37e9ac76a48c6ade00fbcdcba @@ -1,7 +1,8 @@ - + + FileDiffDialog - - + + 0 0 @@ -9,49 +10,49 @@ 491 - + Loading file differences - - + + :/icons/guitone.png:/icons/guitone.png - + - + - - + + false - + false - + - - + + Display Options - + - + - + Qt::Horizontal - + QSizePolicy::MinimumExpanding - + 20 20 @@ -60,25 +61,25 @@ - - + + only left (%1) - - + + only right (%2) - - + + both - + true @@ -87,13 +88,13 @@ - + - + Qt::Horizontal - + 40 20 @@ -102,25 +103,25 @@ - - + + Prev - - + + Next - - + + Close - + true @@ -138,11 +139,12 @@ DiffStatusView QWidget -
../DiffStatusView.h
+
DiffStatusView.h
+ 1
- + @@ -151,11 +153,11 @@ FileDiffDialog accept() - + 490 408 - + 276 217