From 623ff472f7c7c13cbcfa9a74556cc2c4aeae337d Mon Sep 17 00:00:00 2001 From: jeff_schiller Date: Thu, 11 Sep 2008 07:39:53 +0000 Subject: [PATCH] First patch for Bug 209199: Update Win32 Save As dialog to include a Title edit box (and label). This edit box is sync'ed with the RDF and doc-level title and allows a user to edit the title prior to save. This patch does not update the GTK dialogs (that will be submitted in a subsequent patch). --- src/file.cpp | 16 +++- src/ui/dialog/filedialog.cpp | 18 ++-- src/ui/dialog/filedialog.h | 49 ++++++----- src/ui/dialog/filedialogimpl-gtkmm.cpp | 5 +- src/ui/dialog/filedialogimpl-gtkmm.h | 25 +++--- src/ui/dialog/filedialogimpl-win32.cpp | 111 ++++++++++++++++++++++--- src/ui/dialog/filedialogimpl-win32.h | 26 ++++-- 7 files changed, 187 insertions(+), 63 deletions(-) diff --git a/src/file.cpp b/src/file.cpp index b620e9c9e..ac8c0a40e 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -67,6 +67,7 @@ #include "inkscape.h" #include "uri.h" #include "id-clash.h" +#include "dialogs/rdf.h" #ifdef WITH_GNOME_VFS # include @@ -749,13 +750,15 @@ sp_file_save_dialog(Gtk::Window &parentWindow, SPDocument *doc, bool is_copy) } else { dialog_title = (char const *) _("Select file to save to"); } + gchar* doc_title = doc->root->title(); Inkscape::UI::Dialog::FileSaveDialog *saveDialog = Inkscape::UI::Dialog::FileSaveDialog::create( parentWindow, save_loc, Inkscape::UI::Dialog::SVG_TYPES, dialog_title, - default_extension + default_extension, + doc_title ? doc_title : "" ); saveDialog->setSelectionType(extension); @@ -766,6 +769,11 @@ sp_file_save_dialog(Gtk::Window &parentWindow, SPDocument *doc, bool is_copy) return success; } + // set new title here (call RDF to ensure metadata and title element are updated) + rdf_set_work_entity(doc, rdf_find_entity("title"), saveDialog->getDocTitle().c_str()); + // free up old string + if(doc_title) g_free(doc_title); + Glib::ustring fileName = saveDialog->getFilename(); Inkscape::Extension::Extension *selectionType = saveDialog->getSelectionType(); @@ -897,10 +905,10 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri, Inkscape::XML::Document *xml_in_doc = sp_document_repr_doc(in_doc); prevent_id_clashes(doc, in_doc); - + SPObject *in_defs = SP_DOCUMENT_DEFS(in_doc); Inkscape::XML::Node *last_def = SP_OBJECT_REPR(in_defs)->lastChild(); - + SPCSSAttr *style = sp_css_attr_from_object(SP_DOCUMENT_ROOT(doc)); // Count the number of top-level items in the imported document. @@ -945,7 +953,7 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri, if (newgroup) newgroup->appendChild(newitem); else new_obj = place_to_insert->appendChildRepr(newitem); } - + // don't lose top-level defs or style elements else if (SP_OBJECT_REPR(child)->type() == Inkscape::XML::ELEMENT_NODE) { const gchar *tag = SP_OBJECT_REPR(child)->name(); diff --git a/src/ui/dialog/filedialog.cpp b/src/ui/dialog/filedialog.cpp index 08a3230a9..b1ea5dfee 100644 --- a/src/ui/dialog/filedialog.cpp +++ b/src/ui/dialog/filedialog.cpp @@ -88,7 +88,7 @@ FileOpenDialog *FileOpenDialog::create(Gtk::Window &parentWindow, #else FileOpenDialog *dialog = new FileOpenDialogImplGtk(parentWindow, path, fileTypes, title); #endif - + return dialog; } @@ -104,16 +104,17 @@ Glib::ustring FileOpenDialog::getFilename() /** * Public factory method. Used in file.cpp */ -FileSaveDialog *FileSaveDialog::create(Gtk::Window& parentWindow, +FileSaveDialog *FileSaveDialog::create(Gtk::Window& parentWindow, const Glib::ustring &path, FileDialogType fileTypes, const char *title, - const Glib::ustring &default_key) + const Glib::ustring &default_key, + const gchar *docTitle) { #ifdef WIN32 - FileSaveDialog *dialog = new FileSaveDialogImplWin32(parentWindow, path, fileTypes, title, default_key); + FileSaveDialog *dialog = new FileSaveDialogImplWin32(parentWindow, path, fileTypes, title, default_key, docTitle); #else - FileSaveDialog *dialog = new FileSaveDialogImplGtk(parentWindow, path, fileTypes, title, default_key); + FileSaveDialog *dialog = new FileSaveDialogImplGtk(parentWindow, path, fileTypes, title, default_key, docTitle); #endif return dialog; } @@ -123,6 +124,11 @@ Glib::ustring FileSaveDialog::getFilename() return myFilename; } +Glib::ustring FileSaveDialog::getDocTitle() +{ + return myDocTitle; +} + //void FileSaveDialog::change_path(const Glib::ustring& path) //{ // myFilename = path; @@ -162,7 +168,7 @@ void FileSaveDialog::appendExtension(Glib::ustring& path, Inkscape::Extension::O /** * Public factory method. Used in file.cpp */ - FileExportDialog *FileExportDialog::create(Gtk::Window& parentWindow, + FileExportDialog *FileExportDialog::create(Gtk::Window& parentWindow, const Glib::ustring &path, FileDialogType fileTypes, const char *title, diff --git a/src/ui/dialog/filedialog.h b/src/ui/dialog/filedialog.h index b73955b46..eda8c4eb4 100644 --- a/src/ui/dialog/filedialog.h +++ b/src/ui/dialog/filedialog.h @@ -62,8 +62,8 @@ bool hasSuffix(const Glib::ustring &str, const Glib::ustring &ext); /** * Return true if the image is loadable by Gdk, else false */ -bool isValidImageFile(const Glib::ustring &fileName); - +bool isValidImageFile(const Glib::ustring &fileName); + /** * This class provides an implementation-independent API for * file "Open" dialogs. Using a standard interface obviates the need @@ -89,7 +89,7 @@ public: * @param fileTypes one of FileDialogTypes * @param title the title of the dialog */ - static FileOpenDialog *create(Gtk::Window& parentWindow, + static FileOpenDialog *create(Gtk::Window& parentWindow, const Glib::ustring &path, FileDialogType fileTypes, const char *title); @@ -117,15 +117,15 @@ public: Glib::ustring getFilename(); virtual std::vector getFilenames() = 0; - + virtual Glib::ustring getCurrentDirectory() = 0; - + protected: /** * Filename that was given */ Glib::ustring myFilename; - + }; //FileOpenDialog @@ -158,11 +158,12 @@ public: * @param title the title of the dialog * @param key a list of file types from which the user can select */ - static FileSaveDialog *create(Gtk::Window& parentWindow, + static FileSaveDialog *create(Gtk::Window& parentWindow, const Glib::ustring &path, FileDialogType fileTypes, const char *title, - const Glib::ustring &default_key); + const Glib::ustring &default_key, + const gchar *docTitle); /** @@ -191,7 +192,12 @@ public: * Get the file name chosen by the user. Valid after an [OK] */ Glib::ustring getFilename (); - + + /** + * Get the document title chosen by the user. Valid after an [OK] + */ + Glib::ustring getDocTitle (); + virtual Glib::ustring getCurrentDirectory() = 0; protected: @@ -200,12 +206,17 @@ protected: * Filename that was given */ Glib::ustring myFilename; - + + /** + * Doc Title that was given + */ + Glib::ustring myDocTitle; + /** * List of known file extensions. */ std::set knownExtensions; - + void appendExtension(Glib::ustring& path, Inkscape::Extension::Output* outputExtension); @@ -248,7 +259,7 @@ public: * @param title the title of the dialog * @param key a list of file types from which the user can select */ - static FileExportDialog *create(Gtk::Window& parentWindow, + static FileExportDialog *create(Gtk::Window& parentWindow, const Glib::ustring &path, FileDialogType fileTypes, const char *title, @@ -279,28 +290,28 @@ public: * Return the selected filename, if any. If not, return "" */ virtual Glib::ustring getFilename () =0; - + /** * Return the scope of the export. One of the enumerated types - * in ScopeType + * in ScopeType */ virtual ScopeType getScope() = 0; - + /** * Return left side of the exported region */ virtual double getSourceX() = 0; - + /** * Return the top of the exported region */ virtual double getSourceY() = 0; - + /** * Return the width of the exported region */ virtual double getSourceWidth() = 0; - + /** * Return the height of the exported region */ @@ -346,7 +357,7 @@ public: */ virtual unsigned long getBackground() = 0; - + }; //FileExportDialog diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index b93e7837a..541eb388b 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -849,9 +849,12 @@ FileSaveDialogImplGtk::FileSaveDialogImplGtk( Gtk::Window &parentWindow, const Glib::ustring &dir, FileDialogType fileTypes, const Glib::ustring &title, - const Glib::ustring &/*default_key*/ ) : + const Glib::ustring &/*default_key*/, + const gchar* docTitle) : FileDialogBaseGtk(parentWindow, title, Gtk::FILE_CHOOSER_ACTION_SAVE, fileTypes, "dialogs.save_as") { + FileSaveDialog::myDocTitle = docTitle; + /* One file at a time */ set_select_multiple(false); diff --git a/src/ui/dialog/filedialogimpl-gtkmm.h b/src/ui/dialog/filedialogimpl-gtkmm.h index 94067a921..5137b8481 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.h +++ b/src/ui/dialog/filedialogimpl-gtkmm.h @@ -16,9 +16,9 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ - + #include "filedialog.h" - + //General includes #include #include @@ -54,7 +54,7 @@ //For export dialog #include "ui/widget/scalar-unit.h" - + namespace Inkscape { namespace UI @@ -250,7 +250,7 @@ public: Glib::ustring getFilename(); std::vector getFilenames(); - + Glib::ustring getCurrentDirectory(); private: @@ -285,11 +285,12 @@ class FileSaveDialogImplGtk : public FileSaveDialog, public FileDialogBaseGtk { public: - FileSaveDialogImplGtk(Gtk::Window &parentWindow, + FileSaveDialogImplGtk(Gtk::Window &parentWindow, const Glib::ustring &dir, FileDialogType fileTypes, const Glib::ustring &title, - const Glib::ustring &default_key); + const Glib::ustring &default_key, + const gchar* docTitle); virtual ~FileSaveDialogImplGtk(); @@ -381,10 +382,10 @@ public: /** * Return the scope of the export. One of the enumerated types - * in ScopeType + * in ScopeType */ ScopeType getScope() - { + { if (pageButton.get_active()) return SCOPE_PAGE; else if (selectionButton.get_active()) @@ -395,25 +396,25 @@ public: return SCOPE_DOCUMENT; } - + /** * Return left side of the exported region */ double getSourceX() { return sourceX0Spinner.getValue(); } - + /** * Return the top of the exported region */ double getSourceY() { return sourceY1Spinner.getValue(); } - + /** * Return the width of the exported region */ double getSourceWidth() { return sourceWidthSpinner.getValue(); } - + /** * Return the height of the exported region */ diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp index 1f714c3db..ab0a8ec63 100644 --- a/src/ui/dialog/filedialogimpl-win32.cpp +++ b/src/ui/dialog/filedialogimpl-win32.cpp @@ -108,7 +108,7 @@ FileDialogBaseWin32::FileDialogBaseWin32(Gtk::Window &parent, _filter_index = 1; _filter_count = 0; - + _title = (wchar_t*)g_utf8_to_utf16(title, -1, NULL, NULL, NULL); g_assert(_title != NULL); @@ -166,7 +166,7 @@ FileOpenDialogImplWin32::FileOpenDialogImplWin32(Gtk::Window &parent, _preview_image_width = 0; _preview_image_height = 0; _preview_emf_image = false; - + _mutex = NULL; createFilterMenu(); @@ -274,10 +274,10 @@ void FileOpenDialogImplWin32::createFilterMenu() all_image_files.filter_length + all_image_files.name_length + 3 + 1; // Add 3 for 2*2 \0s and a *, and 1 for a trailing \0 - + _filter = new wchar_t[filter_length]; wchar_t *filterptr = _filter; - + for(list::iterator filter_iterator = filter_list.begin(); filter_iterator != filter_list.end(); filter_iterator++) { @@ -303,7 +303,7 @@ void FileOpenDialogImplWin32::createFilterMenu() _extension_map[extension_index++] = filter.mod; } *(filterptr++) = L'\0'; - + _filter_count = extension_index; _filter_index = 2; // Select the 2nd filter in the list - 2 is NOT the 3rd } @@ -314,7 +314,7 @@ void FileOpenDialogImplWin32::GetOpenFileName_thread() g_assert(this != NULL); g_assert(_mutex != NULL); - + WCHAR* current_directory_string = (WCHAR*)g_utf8_to_utf16( _current_directory.data(), _current_directory.length(), NULL, NULL, NULL); @@ -1010,7 +1010,7 @@ MyGetEnhMetaFileW( const WCHAR *filename ) if (hmf) { // Convert Windows Metafile to Enhanced Metafile DWORD nSize = GetMetaFileBitsEx( hmf, 0, NULL ); - + if (nSize) { BYTE *lpvData = new BYTE[nSize]; if (lpvData) { @@ -1447,9 +1447,13 @@ FileSaveDialogImplWin32::FileSaveDialogImplWin32(Gtk::Window &parent, const Glib::ustring &dir, FileDialogType fileTypes, const char *title, - const Glib::ustring &/*default_key*/) : - FileDialogBaseWin32(parent, dir, title, fileTypes, "dialogs.save_as") + const Glib::ustring &/*default_key*/, + const char *docTitle) : + FileDialogBaseWin32(parent, dir, title, fileTypes, "dialogs.save_as"), + _title_label(NULL), + _title_edit(NULL) { + FileSaveDialog::myDocTitle = docTitle; createFilterMenu(); } @@ -1560,9 +1564,11 @@ void FileSaveDialogImplWin32::GetSaveFileName_thread() ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = current_directory_string; ofn.lpstrTitle = _title; - ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER | OFN_ENABLEHOOK; ofn.lpstrFilter = _filter; ofn.nFilterIndex = _filter_index; + ofn.lpfnHook = GetSaveFileName_hookproc; + ofn.lCustData = (LPARAM)this; _result = GetSaveFileNameW(&ofn) != 0; @@ -1590,7 +1596,7 @@ FileSaveDialogImplWin32::show() _result = false; _main_loop = g_main_loop_new(g_main_context_default(), FALSE); - + if(_main_loop != NULL) { if(Glib::Thread::create(sigc::mem_fun(*this, &FileSaveDialogImplWin32::GetSaveFileName_thread), true)) @@ -1599,7 +1605,7 @@ FileSaveDialogImplWin32::show() if(_result) appendExtension(myFilename, (Inkscape::Extension::Output*)_extension); } - + return _result; } @@ -1609,6 +1615,87 @@ void FileSaveDialogImplWin32::setSelectionType( Inkscape::Extension::Extension * } +UINT_PTR CALLBACK FileSaveDialogImplWin32::GetSaveFileName_hookproc( + HWND hdlg, UINT uiMsg, WPARAM, LPARAM lParam) +{ + FileSaveDialogImplWin32 *pImpl = (FileSaveDialogImplWin32*) + GetWindowLongPtr(hdlg, GWLP_USERDATA); + + switch(uiMsg) + { + case WM_INITDIALOG: + { + HWND hParentWnd = GetParent(hdlg); + HINSTANCE hInstance = GetModuleHandle(NULL); + + // get size/pos of typical combo box + RECT rEDT1, rCB1, rROOT, rST; + GetWindowRect(GetDlgItem(hParentWnd, cmb1), &rCB1); + GetWindowRect(GetDlgItem(hParentWnd, cmb13), &rEDT1); + GetWindowRect(GetDlgItem(hParentWnd, stc2), &rST); + GetWindowRect(hdlg, &rROOT); + int ydelta = rCB1.top - rEDT1.top; + + // Make the window a bit longer + RECT rcRect; + GetWindowRect(hParentWnd, &rcRect); + MoveWindow(hParentWnd, rcRect.left, rcRect.top, rcRect.right - rcRect.left, + rcRect.bottom - rcRect.top + ydelta, FALSE); + + // It is not necessary to delete stock objects by calling DeleteObject + HGDIOBJ dlgFont = GetStockObject(DEFAULT_GUI_FONT); + + // Set the pointer to the object + OPENFILENAMEW *ofn = (OPENFILENAMEW*)lParam; + SetWindowLongPtr(hdlg, GWLP_USERDATA, ofn->lCustData); + SetWindowLongPtr(hParentWnd, GWLP_USERDATA, ofn->lCustData); + pImpl = (FileSaveDialogImplWin32*)ofn->lCustData; + + // Create the Title label and edit control + pImpl->_title_label = CreateWindowEx(NULL, "STATIC", "Title:", + WS_VISIBLE|WS_CHILD, + CW_USEDEFAULT, CW_USEDEFAULT, rCB1.left-rST.left, rST.bottom-rST.top, + hParentWnd, NULL, hInstance, NULL); + if(pImpl->_title_label) { + if(dlgFont) SendMessage(pImpl->_title_label, WM_SETFONT, (WPARAM)dlgFont, MAKELPARAM(FALSE, 0)); + SetWindowPos(pImpl->_title_label, NULL, rST.left-rROOT.left, rST.top+ydelta-rROOT.top, + rCB1.left-rST.left, rST.bottom-rST.top, SWP_SHOWWINDOW|SWP_NOZORDER); + } + + pImpl->_title_edit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "", + WS_VISIBLE|WS_CHILD|WS_TABSTOP|ES_AUTOHSCROLL, + CW_USEDEFAULT, CW_USEDEFAULT, rCB1.right-rCB1.left, rCB1.bottom-rCB1.top, + hParentWnd, NULL, hInstance, NULL); + if(pImpl->_title_edit) { + if(dlgFont) SendMessage(pImpl->_title_edit, WM_SETFONT, (WPARAM)dlgFont, MAKELPARAM(FALSE, 0)); + SetWindowPos(pImpl->_title_edit, NULL, rCB1.left-rROOT.left, rCB1.top+ydelta-rROOT.top, + rCB1.right-rCB1.left, rCB1.bottom-rCB1.top, SWP_SHOWWINDOW|SWP_NOZORDER); + // TODO: make sure this works for Unicode + SetWindowText(pImpl->_title_edit, pImpl->myDocTitle.c_str()); + } + } + break; + case WM_DESTROY: + { + if(pImpl->_title_edit) { + int length = GetWindowTextLength(pImpl->_title_edit)+1; + char* temp_title = new char[length]; + GetWindowText(pImpl->_title_edit, temp_title, length); + pImpl->myDocTitle = temp_title; + delete[] temp_title; + DestroyWindow(pImpl->_title_label); + pImpl->_title_label = NULL; + DestroyWindow(pImpl->_title_edit); + pImpl->_title_edit = NULL; + } + } + break; + } + + // Use default dialog behaviour + return 0; +} + } } } diff --git a/src/ui/dialog/filedialogimpl-win32.h b/src/ui/dialog/filedialogimpl-win32.h index 71fccca01..3a0c3775b 100644 --- a/src/ui/dialog/filedialogimpl-win32.h +++ b/src/ui/dialog/filedialogimpl-win32.h @@ -57,7 +57,7 @@ public: protected: /// The dialog type FileDialogType dialogType; - + /// A pointer to the GTK main-loop context object. This /// is used to keep the rest of the inkscape UI running /// while the file dialog is displayed @@ -89,10 +89,10 @@ protected: /// The index of the currently selected filter. /// This value must be greater than or equal to 1, /// and less than or equal to _filter_count. - int _filter_index; - + unsigned int _filter_index; + /// The number of filters registered - int _filter_count; + unsigned int _filter_count; /// An array of the extensions associated with the /// file types of each filter. So the Nth entry of @@ -100,7 +100,7 @@ protected: /// filter in the list. NULL if no specific extension is /// specified/ Inkscape::Extension::Extension **_extension_map; - + /// The currently selected extension. Valid after an [OK] Inkscape::Extension::Extension *_extension; }; @@ -209,11 +209,11 @@ private: /// This flag is set true if a file has been selected bool _file_selected; - + /// This flag is set true when the GetOpenFileName call /// has returned bool _finished; - + /// This mutex is used to ensure that the worker thread /// that calls GetOpenFileName cannot collide with the /// main Inkscape thread @@ -280,7 +280,7 @@ private: /// @return Returns true if the image loaded successfully bool set_emf_preview(); - /// This flag is set true when a meta file is previewed + /// This flag is set true when a meta file is previewed bool _preview_emf_image; /// Renders the unshrunk preview image to a windows HTBITMAP @@ -309,7 +309,8 @@ public: const Glib::ustring &dir, FileDialogType fileTypes, const char *title, - const Glib::ustring &default_key); + const Glib::ustring &default_key, + const char *docTitle); /// Destructor virtual ~FileSaveDialogImplWin32(); @@ -333,6 +334,9 @@ public: virtual void setSelectionType( Inkscape::Extension::Extension *key ); private: + /// A handle to the title label and edit box + HWND _title_label; + HWND _title_edit; /// Create a filter menu for this type of dialog void createFilterMenu(); @@ -341,6 +345,10 @@ private: /// GetSaveFileName void GetSaveFileName_thread(); + /// A message proc which is called by the standard dialog + /// proc + static UINT_PTR CALLBACK GetSaveFileName_hookproc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam); + }; -- 2.30.2