--Big change alert--Currently Olive has a mix of glade windows and gtk.Dialog instances in the small add.py, move.py, mkdir.py, remove.py, etc files. I don't like it, and I hope so do you guys. So what I did is take the bookmark and remove dialogs as examples and started to adapt other dialogs to be the same. In the end the gladefile can be reduced to just the main window and the about dialog. (Next step would be taking those 2 out of glade as well I guess. Since my gtk skills were almost non-existent before this exercise, starting small seemed like a good idea). I choose to put all Dialogs in olive/olivedialogs.py. I think this helps to keep the sourcetree simpler.
As this is a big thing I would very much like to receive comments at this point whether I should continue on this track or leave it be.
Jasper
# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: [EMAIL PROTECTED] # target_branch: https://code.launchpad.net/~bzr-gtk/bzr-gtk/trunk # testament_sha1: 5d57b7566f37e3b094a21f887fe834c36a52fae5 # timestamp: 2008-07-13 16:26:56 +0200 # source_branch: https://code.launchpad.net/~bzr-gtk/bzr-gtk/trunk # base_revision_id: [EMAIL PROTECTED] # # Begin patch === modified file 'olive/__init__.py' --- olive/__init__.py 2008-07-01 21:56:25 +0000 +++ olive/__init__.py 2008-07-13 14:25:41 +0000 @@ -470,9 +470,12 @@ def on_menuitem_add_files_activate(self, widget): """ Add file(s)... menu handler. """ - from add import OliveAdd - add = OliveAdd(self.wt, self.wtpath, self.get_selected_right()) - add.display() + from olivedialogs import AddDialog + add = AddDialog(self.wt, self.wtpath, self.get_selected_right(), self.window) + response = add.run() + add.destroy() + if response == gtk.RESPONSE_OK: + self.refresh_right() def on_menuitem_branch_get_activate(self, widget): """ Branch/Get... menu handler. """ @@ -647,7 +650,7 @@ @show_bzr_error def on_menuitem_branch_revert_activate(self, widget): """ Branch/Revert all changes menu handler. """ - ret = self.wt.revert([]) + ret = self.wt.revert(None) if ret: warning_dialog(_i18n('Conflicts detected'), _i18n('Please have a look at the working tree before continuing.')) @@ -725,9 +728,12 @@ def on_menuitem_file_move_activate(self, widget): """ File/Move... menu handler. """ - from move import OliveMove - move = OliveMove(self.wt, self.wtpath, self.get_selected_right()) - move.display() + from olivedialogs import MoveDialog + move = MoveDialog(self.wt, self.wtpath, self.get_selected_right(), self.window) + response = move.run() + move.destroy() + if response == gtk.RESPONSE_OK: + self.refresh_right() def on_menuitem_file_rename_activate(self, widget): """ File/Rename... menu handler. """ @@ -737,7 +743,7 @@ def on_menuitem_remove_file_activate(self, widget): """ Remove (unversion) selected file. """ - from remove import OliveRemoveDialog + from olivedialogs import RemoveDialog remove = OliveRemoveDialog(self.wt, self.wtpath, selected=self.get_selected_right(), parent=self.window) === modified file 'olive/menu.py' --- olive/menu.py 2008-06-30 12:15:06 +0000 +++ olive/menu.py 2008-07-13 12:56:28 +0000 @@ -327,7 +327,7 @@ def edit_bookmark(self, action): """ Left context menu -> Edit """ - from bookmark import BookmarkDialog + from olivedialogs import BookmarkDialog if self.selected != None: bookmark = BookmarkDialog(self.selected, self.app.window) === added file 'olive/olivedialogs.py' --- olive/olivedialogs.py 1970-01-01 00:00:00 +0000 +++ olive/olivedialogs.py 2008-07-13 14:25:41 +0000 @@ -0,0 +1,290 @@ +# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <[EMAIL PROTECTED]> +# +# 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import os + +try: + import pygtk + pygtk.require("2.0") +except: + pass + +import gtk + +import bzrlib.add +import bzrlib.errors as errors + +from bzrlib.workingtree import WorkingTree +from bzrlib.plugins.gtk import _i18n +from bzrlib.plugins.gtk.dialog import error_dialog +from bzrlib.plugins.gtk.errors import show_bzr_error +from bzrlib.plugins.gtk.olive import Preferences + +class AddDialog(gtk.Dialog): + """ Dialog for adding selected file or recursively all unknown files/folders in branch """ + + def __init__(self, wt, wtpath, selected, parent=None): + """ Initialize the Add dialog. """ + gtk.Dialog.__init__(self, title="Olive - Add file(s)", + parent=parent, + flags=0, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) + + # Get arguments + self.wt = wt + self.wtpath = wtpath + self.selected = selected + + # Create widgets + self._label_add_question = gtk.Label(_i18n("Which file(s) do you want to add?")) + self._radiobutton_add_selected = gtk.RadioButton(None,_i18n("Selected only")) + self._radiobutton_add_unknown = gtk.RadioButton(self._radiobutton_add_selected, _i18n("All unknowns recursively")) + self._button_add = gtk.Button(stock=gtk.STOCK_ADD) + self._button_add.connect('clicked', self._on_add_clicked) + + # Add widgets to dialog window and decorate + self.vbox.add(self._label_add_question) + self.vbox.add(self._radiobutton_add_selected) + self.vbox.add(self._radiobutton_add_unknown) + self.vbox.set_spacing(3) + self.action_area.pack_end(self._button_add) + + self.vbox.show_all() + + @show_bzr_error + def _on_add_clicked(self, button): + """ """ + if self._radiobutton_add_selected.get_active(): + # Add only the selected file + filename = self.selected + + if filename is None: + error_dialog(_i18n('No file was selected'), + _i18n('Please select a file from the list,\nor choose the other option.')) + return + + try: + self.wt.add([filename]) + except errors.NotBranchError: + error_dialog(_i18n('Directory is not a branch'), + _i18n('You can perform this action only in a branch.')) + return + elif self._radiobutton_add_unknown.get_active(): + # Add unknown files recursively + try: + self.wt.add(self.wt.unknowns()) + except errors.NotBranchError: + error_dialog(_i18n('Directory is not a branch'), + _i18n('You can perform this action only in a branch.')) + return + + self.response(gtk.RESPONSE_OK) + +class BookmarkDialog(gtk.Dialog): + """ This class wraps the old Bookmark window into a gtk.Dialog. """ + + def __init__(self, selected, parent=None): + """ Initialize the Bookmark dialog. """ + gtk.Dialog.__init__(self, title="Bookmarks - Olive", + parent=parent, + flags=0, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) + + self.pref = Preferences() + + # Get arguments + self.selected = selected + + # Create widgets + self._label_location = gtk.Label(_i18n("Location:")) + self._label_title = gtk.Label(_i18n("Title:")) + self._entry_location = gtk.Entry() + self._entry_title = gtk.Entry() + self._button_save = gtk.Button(stock=gtk.STOCK_SAVE) + + self._button_save.connect('clicked', self._on_save_clicked) + + # Set default values + self._entry_location.set_text(self.selected) + self._entry_location.set_sensitive(False) + self._entry_title.set_text(self.pref.get_bookmark_title(self.selected)) + self._entry_title.set_flags(gtk.CAN_FOCUS | gtk.HAS_FOCUS) + + # Create a table and put widgets into it + self._table = gtk.Table(rows=2, columns=2) + self._table.attach(self._label_location, 0, 1, 0, 1) + self._table.attach(self._label_title, 0, 1, 1, 2) + self._table.attach(self._entry_location, 1, 2, 0, 1) + self._table.attach(self._entry_title, 1, 2, 1, 2) + + self._label_location.set_alignment(0, 0.5) + self._label_title.set_alignment(0, 0.5) + self._table.set_row_spacings(3) + self._table.set_col_spacings(3) + self.vbox.set_spacing(3) + + self.vbox.add(self._table) + + self.action_area.pack_end(self._button_save) + + self.vbox.show_all() + + @show_bzr_error + def _on_save_clicked(self, button): + """ Save button clicked handler. """ + if self._entry_title.get_text() == '': + error_dialog(_i18n('No title given'), + _i18n('Please specify a title to continue.')) + return + + self.pref.set_bookmark_title(self._entry_location.get_text(), + self._entry_title.get_text()) + self.pref.write() + + self.response(gtk.RESPONSE_OK) + +class MoveDialog(gtk.Dialog): + """ Display the Move dialog and perform the needed actions. """ + def __init__(self, wt, wtpath, selected, parent=None): + """ Initialize the Add dialog. """ + gtk.Dialog.__init__(self, title="Olive - Move", + parent=parent, + flags=0, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) + + # Get arguments + self.wt = wt + self.wtpath = wtpath + self.selected = selected + + if self.selected is None: + self.selected = "" + + if self.wtpath == "": + directory = os.path.dirname(self.wt.abspath(self.selected)) + else: + directory = os.path.dirname(self.wt.abspath(self.wtpath + os.sep + self.selected)) + + # Create widgets + self._hbox = gtk.HBox() + self._label_move_to = gtk.Label(_i18n("Move to")) + self._filechooser_dialog = gtk.FileChooserDialog(title=None, + action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,gtk.STOCK_APPLY, gtk.RESPONSE_OK)) + self.filechooser = gtk.FileChooserButton(self._filechooser_dialog) + self._button_move = gtk.Button(_i18n("Move")) + self._button_move_icon = gtk.Image() + self._button_move_icon.set_from_stock(gtk.STOCK_APPLY, gtk.ICON_SIZE_BUTTON) + self._button_move.set_image(self._button_move_icon) + self._button_move.connect('clicked', self._on_move_clicked) + + # Set location + self._filechooser_dialog.set_current_folder(directory) + + # Add widgets to dialog + self.vbox.add(self._hbox) + self._hbox.add(self._label_move_to) + self._hbox.add(self.filechooser) + self._hbox.set_spacing(5) + self.action_area.pack_end(self._button_move) + + self.vbox.show_all() + + @show_bzr_error + def _on_move_clicked(self, widget): + destination = self.filechooser.get_filename() + + if destination == None: + error_dialog(_i18n('No folder was selected'), + _i18n('Please select a folder to move the selected file to')) + return + + filename = self.selected + + if filename is None: + error_dialog(_i18n('No file was selected'), + _i18n('Please select a file from the list to proceed.')) + return + + source = os.path.join(self.wtpath, filename) + + # Move the file to a directory + wt1, path1 = WorkingTree.open_containing(self.wt.abspath(source)) + wt2, path2 = WorkingTree.open_containing(destination) + if wt1.basedir != wt2.basedir: + error_dialog(_i18n('Not the same branch'), + _i18n('The destination is not in the same branch.')) + return + + wt1.move([source], wt1.relpath(destination)) + + self.response(gtk.RESPONSE_OK) + +class RemoveDialog(gtk.Dialog): + """ This class wraps the old Remove window into a gtk.Dialog. """ + + def __init__(self, wt, wtpath, selected='', parent=None): + """ Initialize the Remove file(s) dialog. """ + gtk.Dialog.__init__(self, title="Remove files - Olive", + parent=parent, + flags=0, + buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)) + + # Get arguments + self.wt = wt + self.wtpath = wtpath + self.selected = selected + + # Create widgets + self._label = gtk.Label(_i18n("Which file(s) do you want to remove?")) + self._radio_selected = gtk.RadioButton(None, _i18n("Selected only"), False) + self._radio_added = gtk.RadioButton(self._radio_selected, _i18n("All files with status 'added'"), False) + self._button_remove = gtk.Button(_i18n("_Remove"), use_underline=True) + + self._button_remove.connect('clicked', self._on_remove_clicked) + + self.vbox.add(self._label) + self.vbox.add(self._radio_added) + self.vbox.add(self._radio_selected) + self.vbox.set_spacing(3) + self.action_area.pack_end(self._button_remove) + + self.vbox.show_all() + + @show_bzr_error + def _on_remove_clicked(self, button): + """ Remove button clicked handler. """ + if self._radio_selected.get_active(): + # Remove only the selected file + filename = self.selected + + if filename is None: + error_dialog(_i18n('No file was selected'), + _i18n('Please select a file from the list,\nor choose the other option.')) + return + + self.wt.remove(os.path.join(self.wtpath, filename)) + elif self._radio_added.get_active(): + # Remove added files recursively + added = self.wt.changes_from(self.wt.basis_tree()).added + file_list = sorted([f[0] for f in added], reverse=True) + if len(file_list) == 0: + warning_dialog(_i18n('No matching files'), + _i18n('No added files were found in the working tree.')) + return + self.wt.remove(file_list) + + self.response(gtk.RESPONSE_OK) # Begin bundle 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
signature.asc
Description: OpenPGP digital signature
-- bzr-gtk mailing list [email protected] Modify settings or unsubscribe at: https://lists.canonical.com/mailman/listinfo/bzr-gtk
