Made FileView columns resizable and movable

Shift-Right Clicking in Windows invokes the explorer context menu


FossilOrigin-Name: 837bdcc1c791b82712aaed52311e783a8fe1a135
This commit is contained in:
kostas 2012-05-03 08:23:02 +00:00
parent e63df45a84
commit ad0eff3dd3
8 changed files with 325 additions and 22 deletions

View File

@ -896,13 +896,9 @@ void MainWindow::updateFileView()
++item_id; ++item_id;
} }
ui->tableView->horizontalHeader()->setResizeMode(COLUMN_STATUS, QHeaderView::ResizeToContents); ui->tableView->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
ui->tableView->horizontalHeader()->setResizeMode(COLUMN_FILENAME, QHeaderView::Stretch); ui->tableView->resizeColumnsToContents();
ui->tableView->horizontalHeader()->setResizeMode(COLUMN_EXTENSION, QHeaderView::ResizeToContents); ui->tableView->horizontalHeader()->setMovable(true);
ui->tableView->horizontalHeader()->setResizeMode(COLUMN_MODIFIED, QHeaderView::ResizeToContents);
if(show_path)
ui->tableView->horizontalHeader()->setResizeMode(COLUMN_PATH, QHeaderView::ResizeToContents);
ui->tableView->horizontalHeader()->setSortIndicatorShown(true);
ui->tableView->resizeRowsToContents(); ui->tableView->resizeRowsToContents();
} }
@ -2411,3 +2407,32 @@ void MainWindow::on_textBrowser_customContextMenuRequested(const QPoint &pos)
menu->addAction(ui->actionClearLog); menu->addAction(ui->actionClearLog);
menu->popup(ui->textBrowser->mapToGlobal(pos)); menu->popup(ui->textBrowser->mapToGlobal(pos));
} }
//------------------------------------------------------------------------------
void MainWindow::on_tableView_customContextMenuRequested(const QPoint &pos)
{
QPoint gpos = QCursor::pos();
#ifdef Q_WS_WIN
if(qApp->keyboardModifiers() & Qt::SHIFT)
{
ui->tableView->selectionModel()->select(ui->tableView->indexAt(pos), QItemSelectionModel::ClearAndSelect|QItemSelectionModel::Rows);
QStringList fnames;
getSelectionFilenames(fnames);
if(fnames.size()==1)
{
QString fname = getCurrentWorkspace() + PATH_SEP + fnames[0];
fname = QDir::toNativeSeparators(fname);
ShowExplorerMenu(winId(), fname, gpos);
}
}
else
#endif
{
QMenu *menu = new QMenu(this);
menu->addActions(ui->tableView->actions());
menu->popup(gpos);
}
}

View File

@ -228,6 +228,8 @@ private slots:
void on_actionDeleteStash_triggered(); void on_actionDeleteStash_triggered();
void on_actionDiffStash_triggered(); void on_actionDiffStash_triggered();
void on_textBrowser_customContextMenuRequested(const QPoint &pos); void on_textBrowser_customContextMenuRequested(const QPoint &pos);
void on_tableView_customContextMenuRequested(const QPoint &pos);
private: private:
enum enum
{ {

View File

@ -77,7 +77,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum> <enum>Qt::CustomContextMenu</enum>
</property> </property>
<property name="editTriggers"> <property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set> <set>QAbstractItemView::NoEditTriggers</set>
@ -104,7 +104,10 @@
<number>20</number> <number>20</number>
</attribute> </attribute>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0"> <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>false</bool> <bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute> </attribute>
<attribute name="verticalHeaderVisible"> <attribute name="verticalHeaderVisible">
<bool>false</bool> <bool>false</bool>

270
Utils.cpp
View File

@ -37,3 +37,273 @@ static bool DialogQueryText(QWidget *parent, const QString &title, const QString
return true; return true;
} }
#endif #endif
#ifdef Q_WS_WIN
// Explorer File Context Menu support. Based on http://www.microsoft.com/msj/0497/wicked/wicked0497.aspx
#include <shlobj.h>
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// FUNCTION: GetNextItem
//
// DESCRIPTION: Finds the next item in an item ID list.
//
// INPUT: pidl = Pointer to an item ID list.
//
// RETURNS: Pointer to the next item.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LPITEMIDLIST GetNextItem (LPITEMIDLIST pidl)
{
USHORT nLen;
if ((nLen = pidl->mkid.cb) == 0)
return NULL;
return (LPITEMIDLIST) (((LPBYTE) pidl) + nLen);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// FUNCTION: GetItemCount
//
// DESCRIPTION: Computes the number of item IDs in an item ID list.
//
// INPUT: pidl = Pointer to an item ID list.
//
// RETURNS: Number of item IDs in the list.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
UINT GetItemCount (LPITEMIDLIST pidl)
{
USHORT nLen;
UINT nCount;
nCount = 0;
while ((nLen = pidl->mkid.cb) != 0) {
pidl = GetNextItem (pidl);
nCount++;
}
return nCount;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// FUNCTION: DuplicateItem
//
// DESCRIPTION: Makes a copy of the next item in an item ID list.
//
// INPUT: pMalloc = Pointer to an IMalloc interface.
// pidl = Pointer to an item ID list.
//
// RETURNS: Pointer to an ITEMIDLIST containing the copied item ID.
//
// NOTES: It is the caller's responsibility to free the memory
// allocated by this function when the item ID is no longer
// needed. Example:
//
// pidlItem = DuplicateItem (pMalloc, pidl);
// .
// .
// .
// pMalloc->lpVtbl->Free (pMalloc, pidlItem);
//
// Failure to free the ITEMIDLIST will result in memory
// leaks.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LPITEMIDLIST DuplicateItem (LPMALLOC pMalloc, LPITEMIDLIST pidl)
{
USHORT nLen;
LPITEMIDLIST pidlNew;
nLen = pidl->mkid.cb;
if (nLen == 0)
return NULL;
pidlNew = (LPITEMIDLIST) pMalloc->Alloc (
nLen + sizeof (USHORT));
if (pidlNew == NULL)
return NULL;
CopyMemory (pidlNew, pidl, nLen);
*((USHORT*) (((LPBYTE) pidlNew) + nLen)) = 0;
return pidlNew;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// FUNCTION: DoExplorerMenu
//
// DESCRIPTION: Given a path name to a file or folder object, displays
// the shell's context menu for that object and executes
// the menu command (if any) selected by the user.
//
// INPUT: hwnd = Handle of the window in which the menu will be
// displayed.
//
// pszPath = Pointer to an ANSI or Unicode string
// specifying the path to the object.
//
// point = x and y coordinates of the point where the
// menu's upper left corner should be located, in
// client coordinates relative to hwnd.
//
// RETURNS: TRUE if successful, FALSE if not.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool ShowExplorerMenu(HWND hwnd, const QString &path, const QPoint &qpoint)
{
LPITEMIDLIST pidlMain, pidlItem, pidlNextItem, *ppidl;
UINT nCount;
POINT point;
point.x = qpoint.x();
point.y = qpoint.y();
WCHAR wchPath[MAX_PATH];
memset(wchPath, 0, sizeof(wchPath));
Q_ASSERT(path.length()<MAX_PATH);
path.toWCharArray(wchPath);
//
// Get pointers to the shell's IMalloc interface and the desktop's
// IShellFolder interface.
//
bool bResult = false;
LPMALLOC pMalloc;
if (!SUCCEEDED (SHGetMalloc (&pMalloc)))
return bResult;
LPSHELLFOLDER psfFolder;
if (!SUCCEEDED (SHGetDesktopFolder (&psfFolder))) {
pMalloc->Release();
return bResult;
}
//
// Convert the path name into a pointer to an item ID list (pidl).
//
ULONG ulCount, ulAttr;
if (SUCCEEDED (psfFolder->ParseDisplayName (hwnd,
NULL, wchPath, &ulCount, &pidlMain, &ulAttr)) && (pidlMain != NULL)) {
if ( (nCount = GetItemCount (pidlMain))>0) { // nCount must be > 0
//
// Initialize psfFolder with a pointer to the IShellFolder
// interface of the folder that contains the item whose context
// menu we're after, and initialize pidlItem with a pointer to
// the item's item ID. If nCount > 1, this requires us to walk
// the list of item IDs stored in pidlMain and bind to each
// subfolder referenced in the list.
//
pidlItem = pidlMain;
while (--nCount) {
//
// Create a 1-item item ID list for the next item in pidlMain.
//
pidlNextItem = DuplicateItem (pMalloc, pidlItem);
if (pidlNextItem == NULL) {
pMalloc->Free(pidlMain);
psfFolder->Release ();
pMalloc->Release ();
return bResult;
}
//
// Bind to the folder specified in the new item ID list.
//
LPSHELLFOLDER psfNextFolder;
if (!SUCCEEDED (psfFolder->BindToObject (
pidlNextItem, NULL, IID_IShellFolder, (void**)&psfNextFolder))) {
pMalloc->Free (pidlNextItem);
pMalloc->Free (pidlMain);
psfFolder->Release ();
pMalloc->Release ();
return bResult;
}
//
// Release the IShellFolder pointer to the parent folder
// and set psfFolder equal to the IShellFolder pointer for
// the current folder.
//
psfFolder->Release ();
psfFolder = psfNextFolder;
//
// Release the storage for the 1-item item ID list we created
// just a moment ago and initialize pidlItem so that it points
// to the next item in pidlMain.
//
pMalloc->Free(pidlNextItem);
pidlItem = GetNextItem (pidlItem);
}
//
// Get a pointer to the item's IContextMenu interface and call
// IContextMenu::QueryContextMenu to initialize a context menu.
//
ppidl = &pidlItem;
LPCONTEXTMENU pContextMenu;
if (SUCCEEDED (psfFolder->GetUIObjectOf (
hwnd, 1, (const ITEMIDLIST **)ppidl, IID_IContextMenu, NULL, (void**)&pContextMenu))) {
HMENU hMenu = CreatePopupMenu ();
if (SUCCEEDED (pContextMenu->QueryContextMenu (
hMenu, 0, 1, 0x7FFF, CMF_EXPLORE))) {
//
// Display the context menu.
//
UINT nCmd = TrackPopupMenu (hMenu, TPM_LEFTALIGN |
TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD,
point.x, point.y, 0, hwnd, NULL);
//
// If a command was selected from the menu, execute it.
//
if (nCmd) {
CMINVOKECOMMANDINFO ici;
memset(&ici, 0, sizeof(ici) );
ici.cbSize = sizeof (CMINVOKECOMMANDINFO);
ici.fMask = 0;
ici.hwnd = hwnd;
ici.lpVerb = MAKEINTRESOURCEA (nCmd - 1);
ici.lpParameters = NULL;
ici.lpDirectory = NULL;
ici.nShow = SW_SHOWNORMAL;
ici.dwHotKey = 0;
ici.hIcon = NULL;
if (SUCCEEDED (
pContextMenu->InvokeCommand (
(CMINVOKECOMMANDINFO*)&ici)))
bResult = true;
}
}
DestroyMenu (hMenu);
pContextMenu->Release ();
}
}
pMalloc->Free (pidlMain);
}
//
// Clean up and return.
//
psfFolder->Release ();
pMalloc->Release ();
return bResult;
}
#endif

View File

@ -6,5 +6,8 @@
QMessageBox::StandardButton DialogQuery(QWidget *parent, const QString &title, const QString &query, QMessageBox::StandardButtons buttons = QMessageBox::Yes|QMessageBox::No); QMessageBox::StandardButton DialogQuery(QWidget *parent, const QString &title, const QString &query, QMessageBox::StandardButtons buttons = QMessageBox::Yes|QMessageBox::No);
#ifdef Q_WS_WIN
bool ShowExplorerMenu(HWND hwnd, const QString &path, const QPoint &qpoint);
#endif
#endif // UTILS_H #endif // UTILS_H

View File

@ -11,7 +11,7 @@ int main(int argc, char *argv[])
#ifdef Q_WS_MACX #ifdef Q_WS_MACX
// Native OSX applications don't use menu icons // Native OSX applications don't use menu icons
a.setAttribute(Qt::AA_DontShowIconsInMenus); app.setAttribute(Qt::AA_DontShowIconsInMenus);
#endif #endif
{ {
bool portable = false; bool portable = false;

View File

@ -1,5 +1,5 @@
C Improved\sRepoFile\spath\sparsing.\sAddresses\s[e462e576e0] C Made\sFileView\scolumns\sresizable\sand\smovable\nShift-Right\sClicking\sin\sWindows\sinvokes\sthe\sexplorer\scontext\smenu\n
D 2012-04-29T12:19:03.560 D 2012-05-03T08:23:02.735
F CommitDialog.cpp a46020a9361151d8d286a2670257d01d8967bf69 F CommitDialog.cpp a46020a9361151d8d286a2670257d01d8967bf69
F CommitDialog.h f1ee8db92103164e7db55a8407ccdcff24571b72 F CommitDialog.h f1ee8db92103164e7db55a8407ccdcff24571b72
F CommitDialog.ui 813d7cba316e226de1a22b7e480bb969fbe9b0c4 F CommitDialog.ui 813d7cba316e226de1a22b7e480bb969fbe9b0c4
@ -8,14 +8,14 @@ F FileActionDialog.h 15db1650b3a13d70bc338371e4c033c66e3b79ce
F FileActionDialog.ui c63644428579741aeb5fa052e237ba799ced9ad7 F FileActionDialog.ui c63644428579741aeb5fa052e237ba799ced9ad7
F FileTableView.cpp 5ddf8c391c9a3ac449ec61fb1db837b577afeec2 F FileTableView.cpp 5ddf8c391c9a3ac449ec61fb1db837b577afeec2
F FileTableView.h 03e56d87c2d46411b9762b87f4d301619aaf18df F FileTableView.h 03e56d87c2d46411b9762b87f4d301619aaf18df
F MainWindow.cpp f6087bb977ddb18d588defc75ac562473a62a1d1 F MainWindow.cpp a98e79e382b67036c2c7012ce082fee179802ccf
F MainWindow.h 675f9a738a5671d366af108a8c7085c7be13f028 F MainWindow.h 90de1726e0961f73f637c4071d1cb0fe1049007f
F MainWindow.ui 6c12a0b141b86c6994d5835618acba19a9ff1976 F MainWindow.ui 8c8182e68aa1955a666997ad83ca692f3cb866d9
F SettingsDialog.cpp e1fad18cc020d08b82c6d35dc94f6624deec9a3b F SettingsDialog.cpp e1fad18cc020d08b82c6d35dc94f6624deec9a3b
F SettingsDialog.h f5da6cab4ccc82e2eb78ec835fb849c4c104d6cc F SettingsDialog.h f5da6cab4ccc82e2eb78ec835fb849c4c104d6cc
F SettingsDialog.ui 8964629ea80c61971c0601624c84d1927902b1fd F SettingsDialog.ui 8964629ea80c61971c0601624c84d1927902b1fd
F Utils.cpp 2587d8073d6c2c1da49622c387cc457a0081f7b5 F Utils.cpp 22c474d8e6d9f58034ee42e42b0e91d33eef262d
F Utils.h a71d82474747466f4c225128d26a703b510230d4 F Utils.h 32e5d344a7f4d27e3ee83006022df007c90470ef
F fuel.pro 880b013acb1136d97c7414372c4e58053cfb153d F fuel.pro 880b013acb1136d97c7414372c4e58053cfb153d
F fuel.rc 8e9ac966f283102c11a77cd7f936cdc09e09bd79 F fuel.rc 8e9ac966f283102c11a77cd7f936cdc09e09bd79
F icons/Address\sBook-01.png ef2cec80ea5a559b72e8be4a344a1869fe69cbd8 F icons/Address\sBook-01.png ef2cec80ea5a559b72e8be4a344a1869fe69cbd8
@ -174,9 +174,9 @@ F icons/fuel.icns 81e535004b62db801a02f3e15d0a33afc9d4070b
F icons/fuel.ico eb529ab3332a17b9302ef3e851db5b9ebce2a038 F icons/fuel.ico eb529ab3332a17b9302ef3e851db5b9ebce2a038
F installer/fuel.iss 13b6a938bcdf273cbd3649d2549887baa1577214 F installer/fuel.iss 13b6a938bcdf273cbd3649d2549887baa1577214
F installer/license.txt 4cc77b90af91e615a64ae04893fdffa7939db84c F installer/license.txt 4cc77b90af91e615a64ae04893fdffa7939db84c
F main.cpp 3741082d40973584d7c9ecddb58721000d6a7f8e F main.cpp f2913af0af1a5fcbebe93fb53b8a9cf6e7bbf65a
F resources.qrc e98383ed205f4e37100c60057e0129c3b86dea53 F resources.qrc e98383ed205f4e37100c60057e0129c3b86dea53
P 1ff2c9dbb0a94e03efea78352c6a63c1d9631d2d P 2508cffe4829804b696668e1159332793cf0d8e7
R 7e5390e09ed77cfe851b3bc850b16cba R 1478f3cff3105545eca56c9fd32f6137
U kostas U kostas
Z 2777a1f831cb30f5e7c955d0dc06c325 Z 340233022700622fcb0724ddcd416ccc

View File

@ -1 +1 @@
2508cffe4829804b696668e1159332793cf0d8e7 837bdcc1c791b82712aaed52311e783a8fe1a135