diff --git a/MainWindow.cpp b/MainWindow.cpp index 298455c..4414be6 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -896,13 +896,9 @@ void MainWindow::updateFileView() ++item_id; } - ui->tableView->horizontalHeader()->setResizeMode(COLUMN_STATUS, QHeaderView::ResizeToContents); - ui->tableView->horizontalHeader()->setResizeMode(COLUMN_FILENAME, QHeaderView::Stretch); - ui->tableView->horizontalHeader()->setResizeMode(COLUMN_EXTENSION, QHeaderView::ResizeToContents); - 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->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); + ui->tableView->resizeColumnsToContents(); + ui->tableView->horizontalHeader()->setMovable(true); ui->tableView->resizeRowsToContents(); } @@ -2411,3 +2407,32 @@ void MainWindow::on_textBrowser_customContextMenuRequested(const QPoint &pos) menu->addAction(ui->actionClearLog); 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); + } + +} diff --git a/MainWindow.h b/MainWindow.h index f1a82e6..32cca8e 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -228,6 +228,8 @@ private slots: void on_actionDeleteStash_triggered(); void on_actionDiffStash_triggered(); void on_textBrowser_customContextMenuRequested(const QPoint &pos); + void on_tableView_customContextMenuRequested(const QPoint &pos); + private: enum { diff --git a/MainWindow.ui b/MainWindow.ui index fa4bea4..a71156c 100644 --- a/MainWindow.ui +++ b/MainWindow.ui @@ -77,7 +77,7 @@ - Qt::ActionsContextMenu + Qt::CustomContextMenu QAbstractItemView::NoEditTriggers @@ -104,7 +104,10 @@ 20 - false + true + + + true false diff --git a/Utils.cpp b/Utils.cpp index 1259f10..d108351 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -37,3 +37,273 @@ static bool DialogQueryText(QWidget *parent, const QString &title, const QString return true; } #endif + + +#ifdef Q_WS_WIN +// Explorer File Context Menu support. Based on http://www.microsoft.com/msj/0497/wicked/wicked0497.aspx + +#include + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// 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()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 + diff --git a/Utils.h b/Utils.h index 7cfbb92..6a6efd5 100644 --- a/Utils.h +++ b/Utils.h @@ -6,5 +6,8 @@ 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 diff --git a/main.cpp b/main.cpp index b287fbb..aea12f8 100644 --- a/main.cpp +++ b/main.cpp @@ -11,7 +11,7 @@ int main(int argc, char *argv[]) #ifdef Q_WS_MACX // Native OSX applications don't use menu icons - a.setAttribute(Qt::AA_DontShowIconsInMenus); + app.setAttribute(Qt::AA_DontShowIconsInMenus); #endif { bool portable = false; diff --git a/manifest b/manifest index 2cd1427..72d3941 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sRepoFile\spath\sparsing.\sAddresses\s[e462e576e0] -D 2012-04-29T12:19:03.560 +C Made\sFileView\scolumns\sresizable\sand\smovable\nShift-Right\sClicking\sin\sWindows\sinvokes\sthe\sexplorer\scontext\smenu\n +D 2012-05-03T08:23:02.735 F CommitDialog.cpp a46020a9361151d8d286a2670257d01d8967bf69 F CommitDialog.h f1ee8db92103164e7db55a8407ccdcff24571b72 F CommitDialog.ui 813d7cba316e226de1a22b7e480bb969fbe9b0c4 @@ -8,14 +8,14 @@ F FileActionDialog.h 15db1650b3a13d70bc338371e4c033c66e3b79ce F FileActionDialog.ui c63644428579741aeb5fa052e237ba799ced9ad7 F FileTableView.cpp 5ddf8c391c9a3ac449ec61fb1db837b577afeec2 F FileTableView.h 03e56d87c2d46411b9762b87f4d301619aaf18df -F MainWindow.cpp f6087bb977ddb18d588defc75ac562473a62a1d1 -F MainWindow.h 675f9a738a5671d366af108a8c7085c7be13f028 -F MainWindow.ui 6c12a0b141b86c6994d5835618acba19a9ff1976 +F MainWindow.cpp a98e79e382b67036c2c7012ce082fee179802ccf +F MainWindow.h 90de1726e0961f73f637c4071d1cb0fe1049007f +F MainWindow.ui 8c8182e68aa1955a666997ad83ca692f3cb866d9 F SettingsDialog.cpp e1fad18cc020d08b82c6d35dc94f6624deec9a3b F SettingsDialog.h f5da6cab4ccc82e2eb78ec835fb849c4c104d6cc F SettingsDialog.ui 8964629ea80c61971c0601624c84d1927902b1fd -F Utils.cpp 2587d8073d6c2c1da49622c387cc457a0081f7b5 -F Utils.h a71d82474747466f4c225128d26a703b510230d4 +F Utils.cpp 22c474d8e6d9f58034ee42e42b0e91d33eef262d +F Utils.h 32e5d344a7f4d27e3ee83006022df007c90470ef F fuel.pro 880b013acb1136d97c7414372c4e58053cfb153d F fuel.rc 8e9ac966f283102c11a77cd7f936cdc09e09bd79 F icons/Address\sBook-01.png ef2cec80ea5a559b72e8be4a344a1869fe69cbd8 @@ -174,9 +174,9 @@ F icons/fuel.icns 81e535004b62db801a02f3e15d0a33afc9d4070b F icons/fuel.ico eb529ab3332a17b9302ef3e851db5b9ebce2a038 F installer/fuel.iss 13b6a938bcdf273cbd3649d2549887baa1577214 F installer/license.txt 4cc77b90af91e615a64ae04893fdffa7939db84c -F main.cpp 3741082d40973584d7c9ecddb58721000d6a7f8e +F main.cpp f2913af0af1a5fcbebe93fb53b8a9cf6e7bbf65a F resources.qrc e98383ed205f4e37100c60057e0129c3b86dea53 -P 1ff2c9dbb0a94e03efea78352c6a63c1d9631d2d -R 7e5390e09ed77cfe851b3bc850b16cba +P 2508cffe4829804b696668e1159332793cf0d8e7 +R 1478f3cff3105545eca56c9fd32f6137 U kostas -Z 2777a1f831cb30f5e7c955d0dc06c325 +Z 340233022700622fcb0724ddcd416ccc diff --git a/manifest.uuid b/manifest.uuid index 8e66e23..04106cc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2508cffe4829804b696668e1159332793cf0d8e7 \ No newline at end of file +837bdcc1c791b82712aaed52311e783a8fe1a135 \ No newline at end of file