diff options
Diffstat (limited to 'portato/gui/gtk')
-rw-r--r-- | portato/gui/gtk/__init__.py | 13 | ||||
-rw-r--r-- | portato/gui/gtk/dialogs.py | 66 | ||||
-rw-r--r-- | portato/gui/gtk/glade/geneticone.glade | 1028 | ||||
-rw-r--r-- | portato/gui/gtk/windows.py | 892 | ||||
-rw-r--r-- | portato/gui/gtk/wrapper.py | 105 |
5 files changed, 2104 insertions, 0 deletions
diff --git a/portato/gui/gtk/__init__.py b/portato/gui/gtk/__init__.py new file mode 100644 index 0000000..85938b4 --- /dev/null +++ b/portato/gui/gtk/__init__.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# +# File: portato/gui/gtk/__init__.py +# This file is part of the Portato-Project, a graphical portage-frontend. +# +# Copyright (C) 2006 René 'Necoro' Neumann +# This is free software. You may redistribute copies of it under the terms of +# the GNU General Public License version 2. +# There is NO WARRANTY, to the extent permitted by law. +# +# Written by René 'Necoro' Neumann <necoro@necoro.net> + +from windows import MainWindow diff --git a/portato/gui/gtk/dialogs.py b/portato/gui/gtk/dialogs.py new file mode 100644 index 0000000..68cd629 --- /dev/null +++ b/portato/gui/gtk/dialogs.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# +# File: portato/gui/gtk/dialogs.py +# This file is part of the Portato-Project, a graphical portage-frontend. +# +# Copyright (C) 2006 René 'Necoro' Neumann +# This is free software. You may redistribute copies of it under the terms of +# the GNU General Public License version 2. +# There is NO WARRANTY, to the extent permitted by law. +# +# Written by René 'Necoro' Neumann <necoro@necoro.net> + +import gtk + +def io_ex_dialog (io_ex): + string = io_ex.strerror + if io_ex.filename: + string = string+": "+io_ex.filename + + dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, string) + ret = dialog.run() + dialog.destroy() + return ret + +def blocked_dialog (blocked, blocks): + dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, blocked+" is blocked by "+blocks+".\nPlease unmerge the blocking package.") + ret = dialog.run() + dialog.destroy() + return ret + +def not_root_dialog (): + errorMB = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, "You are not root.") + ret = errorMB.run() + errorMB.destroy() + return ret + +def unmask_dialog (cpv): + dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, cpv+" seems to be masked.\nDo you want to unmask it and its dependencies?.\n") + ret = dialog.run() + dialog.destroy() + return ret + +def nothing_found_dialog (): + dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "Package not found!") + ret = dialog.run() + dialog.destroy() + return ret + +def changed_flags_dialog (what = "flags"): + hintMB = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, + "You have changed %s. Portato will write these changes into the appropriate files. Please backup them if you think it is necessairy." % what) + ret = hintMB.run() + hintMB.destroy() + return ret + +def remove_deps_dialog (): + infoMB = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, "You cannot remove dependencies. :)") + ret = infoMB.run() + infoMB.destroy() + return ret + +def remove_queue_dialog (): + askMB = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, "Do you really want to clear the whole queue?") + ret = askMB.run() + askMB.destroy() + return ret diff --git a/portato/gui/gtk/glade/geneticone.glade b/portato/gui/gtk/glade/geneticone.glade new file mode 100644 index 0000000..cf187c7 --- /dev/null +++ b/portato/gui/gtk/glade/geneticone.glade @@ -0,0 +1,1028 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> +<!--*- mode: xml -*--> +<glade-interface> + <widget class="GtkWindow" id="MainWindow"> + <property name="border_width">2</property> + <property name="window_position">GTK_WIN_POS_CENTER</property> + <signal name="destroy" handler="cb_destroy"/> + <child> + <widget class="GtkVBox" id="mainVB"> + <property name="visible">True</property> + <child> + <widget class="GtkMenuBar" id="menubar"> + <property name="visible">True</property> + <child> + <widget class="GtkMenuItem" id="fileMenu"> + <property name="visible">True</property> + <property name="label" translatable="yes">_File</property> + <property name="use_underline">True</property> + <child> + <widget class="GtkMenu" id="menu1"> + <property name="visible">True</property> + <child> + <widget class="GtkMenuItem" id="prefItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Preferences</property> + <property name="use_underline">True</property> + <signal name="activate" handler="cb_preferences_clicked"/> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="reloadItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Reload Portage</property> + <property name="use_underline">True</property> + <signal name="activate" handler="cb_reload_clicked"/> + </widget> + </child> + <child> + <widget class="GtkSeparatorMenuItem" id="separatormenuitem1"> + <property name="visible">True</property> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="closeItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Close</property> + <property name="use_underline">True</property> + <signal name="activate" handler="cb_destroy"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="emergeMenu"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Emerge</property> + <property name="use_underline">True</property> + <child> + <widget class="GtkMenu" id="menu2"> + <property name="visible">True</property> + <child> + <widget class="GtkMenuItem" id="emergeItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Emerge</property> + <property name="use_underline">True</property> + <signal name="activate" handler="cb_emerge_clicked"/> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="unmergeItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Unmerge</property> + <property name="use_underline">True</property> + <signal name="activate" handler="cb_unmerge_clicked"/> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="updateItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">Update _World</property> + <property name="use_underline">True</property> + <signal name="activate" handler="cb_update_clicked"/> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="syncItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Sync</property> + <property name="use_underline">True</property> + <signal name="activate" handler="cb_sync_clicked"/> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="saveFlagsItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">Save _Flags</property> + <property name="use_underline">True</property> + <signal name="activate" handler="cb_save_flags_clicked"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="helpMenu"> + <property name="visible">True</property> + <property name="label" translatable="yes">_?</property> + <property name="use_underline">True</property> + <child> + <widget class="GtkMenu" id="menu3"> + <property name="visible">True</property> + <child> + <widget class="GtkMenuItem" id="aboutItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">_About</property> + <property name="use_underline">True</property> + <signal name="activate" handler="cb_about_clicked"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="searchHB"> + <property name="visible">True</property> + <property name="border_width">3</property> + <child> + <widget class="GtkEntry" id="searchEntry"> + <property name="visible">True</property> + <signal name="activate" handler="cb_search_clicked" object="searchEntry"/> + </widget> + <packing> + <property name="padding">5</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="searchButton"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Search</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="cb_search_clicked" object="searchEntry"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVPaned" id="vpaned"> + <property name="visible">True</property> + <property name="position">300</property> + <child> + <widget class="GtkFrame" id="listFrame"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <child> + <widget class="GtkHBox" id="listHB"> + <property name="visible">True</property> + <property name="spacing">5</property> + <property name="homogeneous">True</property> + <child> + <widget class="GtkScrolledWindow" id="catScroll"> + <property name="visible">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <child> + <widget class="GtkTreeView" id="catList"> + <property name="visible">True</property> + <property name="search_column">0</property> + <signal name="cursor_changed" handler="cb_cat_list_selection"/> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkScrolledWindow" id="pkgScroll"> + <property name="visible">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <child> + <widget class="GtkTreeView" id="pkgList"> + <property name="visible">True</property> + <property name="search_column">0</property> + <signal name="cursor_changed" handler="cb_pkg_list_selection"/> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + <child> + <placeholder/> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="resize">False</property> + </packing> + </child> + <child> + <widget class="GtkNotebook" id="notebook"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <child> + <widget class="GtkTable" id="PackageTable"> + <property name="visible">True</property> + <property name="n_rows">4</property> + <property name="n_columns">2</property> + <child> + <widget class="GtkHBox" id="checkHB"> + <property name="visible">True</property> + <property name="spacing">1</property> + <property name="homogeneous">True</property> + <child> + <widget class="GtkCheckButton" id="installedCheck"> + <property name="visible">True</property> + <property name="no_show_all">True</property> + <property name="label" translatable="yes">Installed</property> + <property name="draw_indicator">True</property> + <signal name="button_press_event" handler="cb_button_pressed"/> + </widget> + <packing> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="maskedCheck"> + <property name="visible">True</property> + <property name="no_show_all">True</property> + <property name="label" translatable="yes">Masked</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="cb_masked_toggled"/> + </widget> + <packing> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="testingCheck"> + <property name="visible">True</property> + <property name="no_show_all">True</property> + <property name="label" translatable="yes">Testing</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="cb_testing_toggled"/> + </widget> + <packing> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkHButtonBox" id="buttonBB"> + <property name="visible">True</property> + <property name="border_width">5</property> + <property name="layout_style">GTK_BUTTONBOX_SPREAD</property> + <child> + <widget class="GtkButton" id="pkgEmergeBtn"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Emerge</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="cb_package_emerge_clicked"/> + </widget> + </child> + <child> + <widget class="GtkButton" id="pkgUnmergeBtn"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Unmerge</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="cb_package_unmerge_clicked"/> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="pkgRevertBtn"> + <property name="visible">True</property> + <property name="label" translatable="yes">Re_vert</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="cb_package_revert_clicked"/> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="notInSysLabel"> + <property name="visible">True</property> + <property name="no_show_all">True</property> + <property name="label" translatable="yes"><b>Installed, but not in portage anymore</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="missingLabel"> + <property name="visible">True</property> + <property name="no_show_all">True</property> + <property name="label" translatable="yes"><span foreground='red'><b>MISSING KEYWORD</b></span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="descLabel"> + <property name="visible">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + <property name="y_padding">10</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="comboVB"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options">GTK_FILL</property> + <property name="x_padding">5</property> + </packing> + </child> + <child> + <widget class="GtkScrolledWindow" id="useListScroll"> + <property name="visible">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <child> + <widget class="GtkTreeView" id="useList"> + <property name="visible">True</property> + </widget> + </child> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_padding">5</property> + <property name="y_padding">5</property> + </packing> + </child> + </widget> + <packing> + <property name="tab_expand">False</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Package</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="tab_expand">False</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="queueHB"> + <property name="visible">True</property> + <child> + <widget class="GtkScrolledWindow" id="queueScroll"> + <property name="visible">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <child> + <widget class="GtkTreeView" id="queueList"> + <property name="visible">True</property> + <property name="headers_visible">False</property> + <property name="enable_search">False</property> + <signal name="button_press_event" handler="cb_queue_right_click"/> + <signal name="row_activated" handler="cb_row_activated"/> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkVButtonBox" id="queueBB"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="layout_style">GTK_BUTTONBOX_SPREAD</property> + <child> + <widget class="GtkButton" id="emergeBtn"> + <property name="visible">True</property> + <property name="label" translatable="yes">E_merge</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="cb_emerge_clicked"/> + </widget> + </child> + <child> + <widget class="GtkButton" id="unmergeBtn"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Unmerge</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="cb_unmerge_clicked"/> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="updateBtn"> + <property name="visible">True</property> + <property name="label" translatable="yes">Update _World</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="cb_update_clicked"/> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="removeBtn"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Remove</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="cb_remove_clicked"/> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">5</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + <property name="tab_expand">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes">Queue</property> + <property name="single_line_mode">True</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">1</property> + <property name="tab_expand">False</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="termHB"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">2</property> + <property name="tab_expand">False</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes">Console</property> + <property name="single_line_mode">True</property> + </widget> + <packing> + <property name="type">tab</property> + <property name="position">2</property> + <property name="tab_expand">False</property> + <property name="tab_fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkAlignment" id="alignment4"> + <property name="visible">True</property> + <property name="top_padding">5</property> + <child> + <widget class="GtkLabel" id="statusLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="label" translatable="yes">Portato - A Portage GUI</property> + <property name="single_line_mode">True</property> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkWindow" id="AboutWindow"> + <property name="title" translatable="yes">About</property> + <property name="resizable">False</property> + <property name="modal">True</property> + <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> + <property name="default_width">1</property> + <property name="default_height">1</property> + <property name="destroy_with_parent">True</property> + <property name="skip_taskbar_hint">True</property> + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="aboutLabel"> + <property name="visible">True</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_CENTER</property> + <property name="wrap">True</property> + </widget> + </child> + <child> + <widget class="GtkButton" id="okBtn"> + <property name="visible">True</property> + <property name="label" translatable="yes">_OK</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="close"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkWindow" id="SearchWindow"> + <property name="title" translatable="yes">Search</property> + <property name="resizable">False</property> + <property name="modal">True</property> + <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> + <property name="default_width">1</property> + <property name="default_height">1</property> + <property name="destroy_with_parent">True</property> + <property name="skip_taskbar_hint">True</property> + <child> + <placeholder/> + </child> + </widget> + <widget class="GtkWindow" id="PreferenceWindow"> + <property name="border_width">5</property> + <property name="title" translatable="yes">Preferences</property> + <property name="modal">True</property> + <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property> + <property name="destroy_with_parent">True</property> + <property name="skip_taskbar_hint">True</property> + <child> + <widget class="GtkVBox" id="mainVB"> + <property name="visible">True</property> + <property name="spacing">5</property> + <child> + <widget class="GtkFrame" id="generalFrame"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkCheckButton" id="debugCheck"> + <property name="visible">True</property> + <property name="label" translatable="yes">Debug</property> + <property name="draw_indicator">True</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>General Options</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + </child> + <child> + <widget class="GtkFrame" id="syncFrame"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <child> + <widget class="GtkAlignment" id="alignment5"> + <property name="visible">True</property> + <property name="bottom_padding">5</property> + <property name="left_padding">12</property> + <property name="right_padding">5</property> + <child> + <widget class="GtkHBox" id="syncHB"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="syncLabel"> + <property name="visible">True</property> + <property name="label" translatable="yes">Sync command: </property> + </widget> + <packing> + <property name="expand">False</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="syncCommandEdit"> + <property name="visible">True</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Sync Options</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkFrame" id="updateFrame"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <child> + <widget class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="left_padding">12</property> + <child> + <widget class="GtkVBox" id="updateVB"> + <property name="visible">True</property> + <child> + <widget class="GtkCheckButton" id="deepCheck"> + <property name="visible">True</property> + <property name="label" translatable="yes">--deep</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="fill">False</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="newUseCheck"> + <property name="visible">True</property> + <property name="label" translatable="yes">--newuse</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Update World Options</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkFrame" id="keywordFrame"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <child> + <widget class="GtkAlignment" id="alignment3"> + <property name="visible">True</property> + <property name="bottom_padding">5</property> + <property name="left_padding">12</property> + <property name="right_padding">5</property> + <child> + <widget class="GtkTable" id="keywordTable"> + <property name="visible">True</property> + <property name="n_rows">10</property> + <property name="n_columns">2</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkEntry" id="useFileEdit"> + <property name="visible">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="useEditLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">File name to use, if package.use is a directory: </property> + <property name="single_line_mode">True</property> + </widget> + <packing> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="usePerVersionCheck"> + <property name="visible">True</property> + <property name="label" translatable="yes">Add only exact version to package.use</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="testPerVersionCheck"> + <property name="visible">True</property> + <property name="label" translatable="yes">Add only exact version to package.keywords</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="testEditLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">File name to use, if package.keywords is a directory: </property> + <property name="single_line_mode">True</property> + </widget> + <packing> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="testFileEdit"> + <property name="visible">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="maskFileEdit"> + <property name="visible">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">9</property> + <property name="bottom_attach">10</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="maskEditLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">File name to use, if package.mask/package.unmask is a directory: </property> + <property name="single_line_mode">True</property> + </widget> + <packing> + <property name="top_attach">9</property> + <property name="bottom_attach">10</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="maskPerVersionCheck"> + <property name="visible">True</property> + <property name="label" translatable="yes">Add only exact version to package.mask/package.unmask</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="top_attach">8</property> + <property name="bottom_attach">9</property> + </packing> + </child> + <child> + <widget class="GtkEventBox" id="hintEB"> + <property name="visible">True</property> + <child> + <widget class="GtkFrame" id="hintFrame"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">GTK_SHADOW_OUT</property> + <child> + <widget class="GtkLabel" id="hintLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><u>You may use the following placeholders:</u> + +<i>$(cat)</i>: category +<i>$(pkg)</i>: package name +<i>$(cat-1)/$(cat-2)</i>: first/second part of the category</property> + <property name="use_markup">True</property> + </widget> + </child> + <child> + <placeholder/> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="useLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">5</property> + <property name="label" translatable="yes"><u><i>Use-Flags</i></u></property> + <property name="use_markup">True</property> + <property name="single_line_mode">True</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_padding">6</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="testLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">5</property> + <property name="label" translatable="yes"><u><i>Testing Keywords</i></u></property> + <property name="use_markup">True</property> + <property name="single_line_mode">True</property> + </widget> + <packing> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="y_padding">5</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="maskLabel"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">5</property> + <property name="label" translatable="yes"><u><i>Masking Keywords</i></u></property> + <property name="use_markup">True</property> + <property name="single_line_mode">True</property> + </widget> + <packing> + <property name="top_attach">7</property> + <property name="bottom_attach">8</property> + <property name="y_padding">5</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Use Flag and Keyword Options</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkHButtonBox" id="buttonBox"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="layout_style">GTK_BUTTONBOX_SPREAD</property> + <child> + <widget class="GtkButton" id="okBtn"> + <property name="visible">True</property> + <property name="label" translatable="yes">_OK</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="cb_ok_clicked"/> + </widget> + </child> + <child> + <widget class="GtkButton" id="cancelBtn"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Cancel</property> + <property name="use_underline">True</property> + <signal name="clicked" handler="cb_cancel_clicked"/> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">4</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkMenu" id="queuePopup"> + <property name="visible">True</property> + <child> + <widget class="GtkMenuItem" id="oneShotItem"> + <property name="visible">True</property> + <property name="label" translatable="yes">oneshot</property> + <signal name="activate" handler="cb_oneshot_clicked"/> + </widget> + </child> + </widget> +</glade-interface> diff --git a/portato/gui/gtk/windows.py b/portato/gui/gtk/windows.py new file mode 100644 index 0000000..f4a37fe --- /dev/null +++ b/portato/gui/gtk/windows.py @@ -0,0 +1,892 @@ +# -*- coding: utf-8 -*- +# +# File: portato/gui/gtk/windows.py +# This file is part of the Portato-Project, a graphical portage-frontend. +# +# Copyright (C) 2006 René 'Necoro' Neumann +# This is free software. You may redistribute copies of it under the terms of +# the GNU General Public License version 2. +# There is NO WARRANTY, to the extent permitted by law. +# +# Written by René 'Necoro' Neumann <necoro@necoro.net> + +# gtk stuff +import pygtk +pygtk.require("2.0") +import gtk +import gtk.glade +import gobject + +#our backend stuff +from portato.helper import * +from portato.constants import CONFIG_LOCATION, VERSION, DATA_DIR +from portato import backend +from portato.backend import flags +from portato.backend.exceptions import * + +# more GUI stuff +from portato.gui.gui_helper import Database, Config, EmergeQueue +from dialogs import * +from wrapper import GtkTree, GtkConsole + +# for the terminal +import vte + +# other +from portage_util import unique_array + +class Window: + def __init__ (self): + self.tree = gtk.glade.XML(DATA_DIR+"portato.glade", root = self.__class__.__name__) + self.tree.signal_autoconnect(self) + self.window = self.tree.get_widget(self.__class__.__name__) + + @staticmethod + def watch_cursor (func): + """This is a decorator for functions being so time consuming, that it is appropriate to show the watch-cursor. + @attention: this function relies on the gtk.Window-Object being stored as self.window""" + def wrapper (self, *args, **kwargs): + ret = None + def cb_idle(): + try: + ret = func(self, *args, **kwargs) + finally: + self.window.window.set_cursor(None) + return False + + watch = gtk.gdk.Cursor(gtk.gdk.WATCH) + self.window.window.set_cursor(watch) + gobject.idle_add(cb_idle) + return ret + return wrapper + +class AbstractDialog (Window): + """A class all our dialogs get derived from. It sets useful default vars and automatically handles the ESC-Button.""" + + def __init__ (self, parent): + """Constructor. + + @param parent: the parent window + @type parent: gtk.Window""" + + Window.__init__(self) + + # set parent + self.window.set_transient_for(parent) + + # catch the ESC-key + self.window.connect("key-press-event", self.cb_key_pressed) + + def cb_key_pressed (self, widget, event): + """Closes the window if ESC is pressed.""" + keyname = gtk.gdk.keyval_name(event.keyval) + if keyname == "Escape": + self.close() + return True + else: + return False + + def close (self, *args): + self.window.destroy() + +class AboutWindow (AbstractDialog): + """A window showing the "about"-informations.""" + + def __init__ (self, parent): + """Constructor. + + @param parent: the parent window + @type parent: gtk.Window""" + + AbstractDialog.__init__(self, parent) + + label = self.tree.get_widget("aboutLabel") + label.set_markup(""" +<big><b>Portato v.%s</b></big> +A Portage-GUI + +This software is licensed under the terms of the GPLv2. +Copyright (C) 2006 René 'Necoro' Neumann <necoro@necoro.net> + +<small>Thanks to Fred for support and ideas :P</small> +""" % VERSION) + + self.window.show_all() + +class SearchWindow (AbstractDialog): + """A window showing the results of a search process.""" + + def __init__ (self, parent, list, jump_to): + """Constructor. + + @param parent: parent-window + @type parent: gtk.Window + @param list: list of results to show + @type list: string[] + @param jump_to: function to call if "OK"-Button is hit + @type jump_to: function(string)""" + + AbstractDialog.__init__(self, parent) + + self.list = list # list to show + self.jump_to = jump_to # function to call for jumping + + # combo box + self.combo = gtk.combo_box_new_text() + for x in list: + self.combo.append_text(x) + self.combo.set_active(0) # first item + self.combo.connect("key-press-event", self.cb_key_pressed_combo) + + self.window.add(self.combo) + + # finished --> show + self.window.show_all() + + def cb_key_pressed_combo (self, widget, event): + """Emulates a ok-button-click.""" + keyname = gtk.gdk.keyval_name(event.keyval) + if keyname == "Return": # take it as an "OK" if Enter is pressed + self.window.destroy() + self.jump_to(self.list[self.combo.get_active()]) + return True + else: + return False + +class PreferenceWindow (AbstractDialog): + """Window displaying some preferences.""" + + # all checkboxes in the window + # widget name -> option name + checkboxes = { + "debugCheck" : "debug_opt", + "deepCheck" : "deep_opt", + "newUseCheck" : "newuse_opt", + "maskPerVersionCheck" : "maskPerVersion_opt", + "usePerVersionCheck" : "usePerVersion_opt", + "testPerVersionCheck" : "testingPerVersion_opt" + } + + # all edits in the window + # widget name -> option name + edits = { + "maskFileEdit" : "maskFile_opt", + "testFileEdit" : "testingFile_opt", + "useFileEdit" : "useFile_opt", + "syncCommandEdit" : "syncCmd_opt" + } + + def __init__ (self, parent, cfg): + """Constructor. + + @param parent: parent window + @type parent: gtk.Window + @param cfg: configuration object + @type cfg: gui_helper.Config""" + + AbstractDialog.__init__(self, parent) + + # our config + self.cfg = cfg + + # set the bg-color of the hint + hintEB = self.tree.get_widget("hintEB") + hintEB.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#f3f785")) + + for box in self.checkboxes: + self.tree.get_widget(box).\ + set_active(self.cfg.get_boolean(self.checkboxes[box])) + + for edit in self.edits: + self.tree.get_widget(edit).\ + set_text(self.cfg.get(self.edits[edit])) + + self.window.show_all() + + def _save(self): + """Sets all options in the Config-instance.""" + + for box in self.checkboxes: + self.cfg.set_boolean(self.checkboxes[box], self.tree.get_widget(box).get_active()) + + for edit in self.edits: + self.cfg.set(self.edits[edit],self.tree.get_widget(edit).get_text()) + + def cb_ok_clicked(self, button): + """Saves, writes to config-file and closes the window.""" + self._save() + try: + self.cfg.write() + except IOError, e: + io_ex_dialog(e) + + self.window.destroy() + + def cb_cancel_clicked (self, button): + """Just closes - w/o saving.""" + self.window.destroy() + +class PackageTable: + """A window with data about a specfic package.""" + + def __init__ (self, main): + """Build up window contents. + + @param main: the main window + @type main: MainWindow""" + + self.main = main + self.tree = main.tree + self.window = main.window + self.tree.signal_autoconnect(self) + + # the table + self.table = self.tree.get_widget("PackageTable") + + # chechboxes + self.installedCheck = self.tree.get_widget("installedCheck") + self.maskedCheck = self.tree.get_widget("maskedCheck") + self.testingCheck = self.tree.get_widget("testingCheck") + + # labels + self.notInSysLabel = self.tree.get_widget("notInSysLabel") + self.missingLabel = self.tree.get_widget("missingLabel") + + # buttons + self.emergeBtn = self.tree.get_widget("pkgEmergeBtn") + self.unmergeBtn = self.tree.get_widget("pkgUnmergeBtn") + self.cancelBtn = self.tree.get_widget("pkgCancelBtn") + + # useList + self.useListScroll = self.tree.get_widget("useListScroll") + self.useList = None + + def update (self, cp, queue = None, version = None, doEmerge = True, instantChange = False): + """Updates the table to show the contents for the package. + + @param cp: the selected package + @type cp: string (cp) + @param queue: emerge-queue (if None the emerge-buttons are disabled) + @type queue: EmergeQueue + @param version: if not None, specifies the version to select + @type version: string + @param doEmerge: if False, the emerge buttons are disabled + @type doEmerge: False + @param instantChange: if True the changed keywords are updated instantly + @type instantChange: boolean""" + + self.cp = cp # category/package + self.version = version # version - if not None this is used + self.queue = queue + self.doEmerge = doEmerge + self.instantChange = instantChange + + # packages and installed packages + self.packages = backend.sort_package_list(backend.get_all_versions(cp)) + self.instPackages = backend.sort_package_list(backend.get_all_installed_versions(cp)) + + # version-combo-box + self.vCombo = self.build_vers_combo() + if not self.doEmerge: self.vCombo.set_sensitive(False) + vb = self.tree.get_widget("comboVB") + children = vb.get_children() + if children: + for c in children: vb.remove(c) + vb.pack_start(self.vCombo) + + # the label (must be here, because it depends on the combo box) + desc = self.actual_package().get_env_var("DESCRIPTION").replace("&","&") + if not desc: + desc = "<no description>" + use_markup = False + else: + desc = "<b>"+desc+"</b>" + use_markup = True + desc = "<i><u>"+self.actual_package().get_cp()+"</u></i>\n\n"+desc + self.descLabel = self.tree.get_widget("descLabel") + self.descLabel.set_use_markup(use_markup) + self.descLabel.set_label(desc) + + if not self.queue or not self.doEmerge: + self.emergeBtn.set_sensitive(False) + self.unmergeBtn.set_sensitive(False) + + # current status + self.cb_combo_changed(self.vCombo) + self.table.show_all() + + def fill_use_list(self, store): + """Fills a given ListStore with the use-flag data. + + @param store: the store to fill + @type store: gtk.ListStore""" + + pkg = self.actual_package() + pkg_flags = pkg.get_all_use_flags() + pkg_flags.sort() + for use in pkg_flags: + if pkg.is_installed() and use in pkg.get_actual_use_flags(): # flags set during install + enabled = True + elif (not pkg.is_installed()) and use in pkg.get_settings("USE").split() and not flags.invert_use_flag(use) in pkg.get_new_use_flags(): # flags that would be set + enabled = True + elif use in pkg.get_new_use_flags(): + enabled = True + else: + enabled = False + store.append([enabled, use, backend.get_use_desc(use, self.cp)]) + + return store + + def build_use_list (self): + """Builds the useList.""" + store = gtk.ListStore(bool, str, str) + self.fill_use_list(store) + + # build view + view = gtk.TreeView(store) + cell = gtk.CellRendererText() + tCell = gtk.CellRendererToggle() + tCell.set_property("activatable", True) + tCell.connect("toggled", self.cb_use_flag_toggled, store) + view.append_column(gtk.TreeViewColumn("Enabled", tCell, active = 0)) + view.append_column(gtk.TreeViewColumn("Flags", cell, text = 1)) + view.append_column(gtk.TreeViewColumn("Description", cell, text = 2)) + + if store.iter_n_children(None) == 0: # if there are no nodes in the list ... + view.set_child_visible(False) # ... do not show the list + else: + view.set_child_visible(True) + return view + + def build_vers_combo (self): + """Creates the combo box with the different versions.""" + combo = gtk.combo_box_new_text() + + # append versions + for s in [x.get_version() for x in self.packages]: + combo.append_text(s) + + # activate the first one + try: + best_version = "" + if self.version: + best_version = self.version + else: + best_version = backend.find_best_match(self.packages[0].get_cp(), (self.instPackages != [])).get_version() + for i in range(len(self.packages)): + if self.packages[i].get_version() == best_version: + combo.set_active(i) + break + except AttributeError: # no package found + debug('catched AttributeError => no "best package" found. Selected first one.') + combo.set_active(0) + + combo.connect("changed", self.cb_combo_changed) + + return combo + + def actual_package (self): + """Returns the actual selected package. + + @returns: the actual selected package + @rtype: backend.Package""" + + return self.packages[self.vCombo.get_active()] + + def _update_keywords (self, emerge, update = False): + if emerge: + try: + try: + self.queue.append(self.actual_package().get_cpv(), unmerge = False, update = update) + except backend.PackageNotFoundException, e: + if unmask_dialog(e[0]) == gtk.RESPONSE_YES: + self.queue.append(self.actual_package().get_cpv(), unmerge = False, unmask = True, update = update) + except BlockedException, e: + blocked_dialog(e[0], e[1]) + else: + try: + self.queue.append(self.actual_package().get_cpv(), unmerge = True) + except backend.PackageNotFoundException, e: + masked_dialog(e[0]) + + def cb_combo_changed (self, combo): + """Callback for the changed ComboBox. + It then rebuilds the useList and the checkboxes.""" + + # remove old useList + w = self.useListScroll.get_child() + if w: + self.useListScroll.remove(w) + + # build new + self.useList = self.build_use_list() + self.useListScroll.add(self.useList) + pkg = self.actual_package() + + # + # rebuild the buttons and checkboxes in all the different manners which are possible + # + if (not pkg.is_in_system()) or pkg.is_missing_keyword(): + if not pkg.is_in_system(): + self.missingLabel.hide() + self.notInSysLabel.show() + else: # missing keyword + self.missingLabel.show() + self.notInSysLabel.hide() + + self.installedCheck.hide() + self.maskedCheck.hide() + self.testingCheck.hide() + self.emergeBtn.set_sensitive(False) + else: + self.missingLabel.hide() + self.notInSysLabel.hide() + self.installedCheck.show() + self.maskedCheck.show() + self.testingCheck.show() + if self.doEmerge: + self.emergeBtn.set_sensitive(True) + self.installedCheck.set_active(pkg.is_installed()) + self.maskedCheck.set_active(pkg.is_masked()) + if pkg.is_testing(allowed = False) and not pkg.is_testing(allowed=True): + self.testingCheck.set_label("<i>(Testing)</i>") + self.testingCheck.get_child().set_use_markup(True) + else: + self.testingCheck.set_label("Testing") + self.testingCheck.set_active(pkg.is_testing(allowed = False)) + + if self.doEmerge: + # set emerge-button-label + if not self.actual_package().is_installed(): + self.emergeBtn.set_label("_Emerge") + self.unmergeBtn.set_sensitive(False) + else: + self.emergeBtn.set_label("R_emerge") + self.unmergeBtn.set_sensitive(True) + + self.table.show_all() + + return True + + def cb_button_pressed (self, b, event): + """Callback for pressed checkboxes. Just quits the event-loop - no redrawing.""" + if not isinstance(b, gtk.CellRendererToggle): + b.emit_stop_by_name("button-press-event") + return True + + def cb_package_revert_clicked (self, button): + """Callback for pressed cancel-button. Closes the window.""" + self.actual_package().remove_new_use_flags() + self.actual_package().remove_new_masked() + self.actual_package().remove_new_testing() + self.cb_combo_changed(self.vCombo) + if self.instantChange: + self._update_keywords(True, update = True) + return True + + def cb_package_emerge_clicked (self, button): + """Callback for pressed emerge-button. Adds the package to the EmergeQueue.""" + if not am_i_root(): + not_root_dialog() + else: + self._update_keywords(True) + self.main.notebook.set_current_page(self.main.QUEUE_PAGE) + return True + + def cb_package_unmerge_clicked (self, button): + """Callback for pressed unmerge-button clicked. Adds the package to the UnmergeQueue.""" + if not am_i_root(): + not_root_dialog() + else: + self._update_keywords(False) + self.main.notebook.set_current_page(self.main.QUEUE_PAGE) + return True + + def cb_testing_toggled (self, button): + """Callback for toggled testing-checkbox.""" + status = button.get_active() + + if self.actual_package().is_testing(allowed = False) == status: + return False + + if not self.actual_package().is_testing(allowed = True): + self.actual_package().set_testing(False) + button.set_label("Testing") + button.set_active(True) + else: + self.actual_package().set_testing(True) + if self.actual_package().is_testing(allowed=False): + button.set_label("<i>(Testing)</i>") + button.get_child().set_use_markup(True) + button.set_active(True) + + if self.instantChange: + self._update_keywords(True, update = True) + + return True + + def cb_masked_toggled (self, button): + """Callback for toggled masking-checkbox.""" + status = button.get_active() + self.actual_package().set_masked(status) + + if self.instantChange: + self._update_keywords(True, update = True) + + return True + + def cb_use_flag_toggled (self, cell, path, store): + """Callback for a toggled use-flag button.""" + store[path][0] = not store[path][0] + prefix = "" + if not store[path][0]: + prefix = "-" + self.actual_package().set_use_flag(prefix+store[path][1]) + + if self.instantChange: + self._update_keywords(True, update = True) + + return True + +class MainWindow (Window): + """Application main window.""" + + # NOTEBOOK PAGE CONSTANTS + PKG_PAGE = 0 + QUEUE_PAGE = 1 + CONSOLE_PAGE = 2 + + def __init__ (self): + """Build up window""" + + # main window stuff + Window.__init__(self) + self.window.set_title(("Portato (%s)" % VERSION)) + mHeight = 800 + if gtk.gdk.screen_height() <= 800: mHeight = 600 + self.window.set_geometry_hints (self.window, min_width = 600, min_height = mHeight, max_height = gtk.gdk.screen_height(), max_width = gtk.gdk.screen_width()) + + # booleans + self.doUpdate = False + self.packageInit = True + + # package db + self.db = Database() + self.db.populate() + + # config + try: + self.cfg = Config(CONFIG_LOCATION) + except IOError, e: + io_ex_dialog(e) + raise e + + self.cfg.modify_external_configs() + + # set vpaned position + vpaned = self.tree.get_widget("vpaned") + vpaned.set_position(mHeight/2) + + # cat and pkg list + self.catList = self.tree.get_widget("catList") + self.pkgList = self.tree.get_widget("pkgList") + self.build_cat_list() + self.build_pkg_list() + + # queue list + self.queueList = self.tree.get_widget("queueList") + self.build_queue_list() + + # the terminal + term = vte.Terminal() + term.set_scrollback_lines(1024) + term.set_scroll_on_output(True) + term.set_font_from_string("Monospace 11") + # XXX why is this not working with the colors + term.set_color_background(gtk.gdk.color_parse("white")) + term.set_color_foreground(gtk.gdk.color_parse("black")) + termHB = self.tree.get_widget("termHB") + termScroll = gtk.VScrollbar(term.get_adjustment()) + termHB.pack_start(term, True, True) + termHB.pack_start(termScroll, False) + + # notebook + self.notebook = self.tree.get_widget("notebook") + self.window.show_all() + + # table + self.packageTable = PackageTable(self) + self.packageTable.table.hide_all() + + # popup + popupTree = gtk.glade.XML(DATA_DIR+"portato.glade", root = "queuePopup") + popupTree.signal_autoconnect(self) + self.queuePopup = popupTree.get_widget("queuePopup") + + # set emerge queue + self.queueTree = GtkTree(self.queueList.get_model()) + self.queue = EmergeQueue(console = GtkConsole(term), tree = self.queueTree, db = self.db) + + def show_package (self, *args, **kwargs): + self.packageTable.update(*args, **kwargs) + self.notebook.set_current_page(self.PKG_PAGE) + + def build_queue_list (self): + """Builds the queue list.""" + + store = gtk.TreeStore(str,str) + + self.queueList.set_model(store) + + cell = gtk.CellRendererText() + col = gtk.TreeViewColumn("Queue", cell, text = 0) + self.queueList.append_column(col) + + col = gtk.TreeViewColumn("Options", cell, markup = 1) + self.queueList.append_column(col) + + def build_cat_list (self): + """Builds the category list.""" + + store = gtk.ListStore(str) + + # build categories + for p in backend.list_categories(): + store.append([p]) + # sort them alphabetically + store.set_sort_column_id(0, gtk.SORT_ASCENDING) + + self.catList.set_model(store) + cell = gtk.CellRendererText() + col = gtk.TreeViewColumn("Categories", cell, text = 0) + self.catList.append_column(col) + + def build_pkg_list (self, name = None): + """Builds the package list. + + @param name: name of the selected catetegory + @type name: string""" + + store = gtk.ListStore(str) + self.fill_pkg_store(store,name) + + # build view + self.pkgList.set_model(store) + cell = gtk.CellRendererText() + col = gtk.TreeViewColumn("Packages", cell, text = 0) + self.pkgList.append_column(col) + + def fill_pkg_store (self, store, name = None): + """Fills a given ListStore with the packages in a category. + + @param store: the store to fill + @type store: gtk.ListStore + @param name: the name of the category + @type name: string + @returns: the filled store + @rtype: gtk.ListStore""" + + if name: + for p in self.db.get_cat(name): + store.append([p]) + return store + + def jump_to (self, cp): + """Is called when we want to jump to a specific package.""" + self.show_package(cp, self.queue) + + def cb_cat_list_selection (self, view): + """Callback for a category-list selection. Updates the package list with the packages in the category.""" + # get the selected category + sel = view.get_selection() + store, it = sel.get_selected() + if it: + self.selCatName = store.get_value(it, 0) + self.pkgList.get_model().clear() + self.fill_pkg_store(self.pkgList.get_model(), self.selCatName) + return True + + def cb_pkg_list_selection (self, view): + """Callback for a package-list selection. Updates the package info.""" + sel = view.get_selection() + store, it = sel.get_selected() + if it: + package = store.get_value(it, 0) + if package[-1] == '*': package = package[:-1] + self.show_package(self.selCatName+"/"+package, self.queue) + return True + + def cb_row_activated (self, view, path, *args): + """Callback for an activated row in the emergeQueue. Opens a package window.""" + store = self.queueTree + if len(path) > 1: + iterator = store.get_original().get_iter(path) + if store.is_in_emerge(iterator): + package = store.get_value(iterator, 0) + cat, name, vers, rev = backend.split_package_name(package) + if rev != "r0": vers = vers+"-"+rev + self.show_package(cat+"/"+name, queue = self.queue, version = vers, instantChange = True, doEmerge = False) + return True + + def cb_emerge_clicked (self, action): + """Do emerge.""" + + self.notebook.set_current_page(self.CONSOLE_PAGE) + + if len(flags.newUseFlags) > 0: + changed_flags_dialog("use flags") + flags.write_use_flags() + + if len(flags.new_masked)>0 or len(flags.new_unmasked)>0 or len(flags.newTesting)>0: + debug("new masked:",flags.new_masked) + debug("new unmasked:", flags.new_unmasked) + debug("new testing:", flags.newTesting) + changed_flags_dialog("masking keywords") + flags.write_masked() + flags.write_testing() + backend.reload_settings() + + if not self.doUpdate: + self.queue.emerge(force=True) + else: + self.queue.update_world(force=True, newuse = self.cfg.get_boolean("newuse_opt"), deep = self.cfg.get_boolean("deep_opt")) + self.doUpdate = False + + def cb_unmerge_clicked (self, button): + """Do unmerge.""" + + self.notebook.set_current_page(self.CONSOLE_PAGE) + self.queue.unmerge(force=True) + return True + + @Window.watch_cursor + def cb_update_clicked (self, action): + if not backend.am_i_root(): + not_root_dialog() + + else: + updating = backend.update_world(newuse = self.cfg.get_boolean("newuse_opt"), deep = self.cfg.get_boolean("deep_opt")) + + debug("updating list:", [(x.get_cpv(), y.get_cpv()) for x,y in updating]) + try: + for pkg, old_pkg in updating: + self.queue.append(pkg.get_cpv()) + except BlockedException, e: + blocked_dialog(e[0], e[1]) + if len(updating): self.doUpdate = True + return True + + def cb_remove_clicked (self, button): + """Removes a selected item in the (un)emerge-queue if possible.""" + selected = self.queueList.get_selection() + + if selected: + model, iter = selected.get_selected() + + if iter == None: return False + + if not model.iter_parent(iter): # top-level + if model.iter_n_children(iter) > 0: # and has children which can be removed :) + if remove_queue_dialog() == gtk.RESPONSE_YES : + self.queue.remove_children(iter) + self.doUpdate = False + + elif model.iter_parent(model.iter_parent(iter)): # this is in the 3rd level => dependency + remove_deps_dialog() + else: + self.queue.remove_children(iter) # remove children first + self.queue.remove(iter) + self.doUpdate = False + + return True + + def cb_sync_clicked (self, action): + if not backend.am_i_root(): + not_root_dialog() + else: + self.notebook.set_current_page(self.CONSOLE_PAGE) + cmd = self.cfg.get("syncCmd_opt") + + if cmd != "emerge --sync": + cmd = cmd.split() + self.queue.sync(cmd) + else: + self.queue.sync() + + def cb_save_flags_clicked (self, action): + if not backend.am_i_root(): + not_root_dialog() + else: + flags.write_use_flags() + flags.write_testing() + flags.write_masked() + + @Window.watch_cursor + def cb_reload_clicked (self, action): + """Reloads the portage settings and the database.""" + backend.reload_settings() + del self.db + self.db = Database() + self.db.populate() + + @Window.watch_cursor + def cb_search_clicked (self, entry): + """Do a search.""" + if entry.get_text() != "": + packages = backend.find_all_packages(entry.get_text(), withVersion = False) + + if packages == []: + nothing_found_dialog() + else: + if len(packages) == 1: + self.jump_to(packages[0]) + else: + SearchWindow(self.window, packages, self.jump_to) + + def cb_preferences_clicked (self, button): + PreferenceWindow(self.window, self.cfg) + return True + + def cb_about_clicked (self, button): + AboutWindow(self.window) + return True + + def cb_queue_right_click (self, queue, event): + if event.button == 3: + x = int(event.x) + y = int(event.y) + time = event.time + pthinfo = queue.get_path_at_pos(x, y) + if pthinfo is not None: + path, col, cellx, celly = pthinfo + if self.queueTree.is_in_emerge(self.queueTree.get_original().get_iter(path)): + queue.grab_focus() + queue.set_cursor(path, col, 0) + self.queuePopup.popup(None, None, None, event.button, time) + return True + else: + return False + + def cb_oneshot_clicked (self, action): + sel = self.queueList.get_selection() + store, it = sel.get_selected() + if it: + package = store.get_value(it, 0) + if not self.cfg.get_local(package, "oneshot_opt"): + set = True + else: + set = False + + self.cfg.set_local(package, "oneshot_opt", set) + self.queue.append(package, update = True, oneshot = set, forceUpdate = True) + + def cb_destroy (self, widget): + """Calls main_quit().""" + gtk.main_quit() + + def main (self): + """Main.""" + gobject.threads_init() + # now subthreads can run normally, but are not allowed to touch the GUI. If threads should change sth there - use gobject.idle_add(). + # for more informations on threading and gtk: http://www.async.com.br/faq/pygtk/index.py?req=show&file=faq20.006.htp + gtk.main() diff --git a/portato/gui/gtk/wrapper.py b/portato/gui/gtk/wrapper.py new file mode 100644 index 0000000..7066acb --- /dev/null +++ b/portato/gui/gtk/wrapper.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +# +# File: portato/gui/gtk/wrapper.py +# This file is part of the Portato-Project, a graphical portage-frontend. +# +# Copyright (C) 2006 René 'Necoro' Neumann +# This is free software. You may redistribute copies of it under the terms of +# the GNU General Public License version 2. +# There is NO WARRANTY, to the extent permitted by law. +# +# Written by René 'Necoro' Neumann <necoro@necoro.net> + +from portato.gui.wrapper import Tree, Console + +class GtkTree (Tree): + """The implementation of the abstract tree.""" + + def __init__ (self, tree, col = 0): + """Constructor. + + @param tree: original tree + @type tree: gtk.TreeStore + @param col: the column where the cpv is stored + @type col: int""" + + self.tree = tree + self.cpv_col = col + self.emergeIt = self.append(None, ["Emerge", ""]) + self.unmergeIt = self.append(None, ["Unmerge", ""]) + + def build_append_value (self, cpv, oneshot = False, update = False, version = None): + string = "" + + if oneshot: + string += "<i>oneshot</i>" + if update: string += "; " + + if update: + string += "<i>updating</i>" + if version != None: + string += "<i> from version %s</i>" % version + + return [cpv, string] + + def get_emerge_it (self): + return self.emergeIt + + def get_unmerge_it (self): + return self.unmergeIt + + def is_in_emerge (self, it): + return self.get_path_from_iter(it).split(":")[0] == self.get_path_from_iter(self.emergeIt) + + def is_in_unmerge (self, it): + return self.get_path_from_iter(it).split(":")[0] == self.get_path_from_iter(self.unmergeIt) + + def iter_has_parent (self, it): + return (self.tree.iter_parent(it) != None) + + def parent_iter (self, it): + return self.tree.iter_parent(it) + + def first_child_iter (self, it): + return self.tree.iter_children(it) + + def iter_has_children (self, it): + return self.tree.iter_has_child(it) + + def next_iter (self, it): + return self.tree.iter_next(it) + + def get_value (self, it, column): + return self.tree.get_value(it, column) + + def get_path_from_iter (self, it): + return self.tree.get_string_from_iter(it) + + def append (self, parent = None, values = None): + return self.tree.append(parent, values) + + def remove (self, it): + return self.tree.remove(it) + + def get_original (self): + return self.tree + + def get_cpv_column (self): + return self.cpv_col + +class GtkConsole (Console): + """The implementation of the abstract Console for GTK.""" + + def __init__ (self, console): + """Constructor. + + @param console: the original console + @type console: vte.Terminal""" + + self.console = console + + def set_pty (self, pty): + self.console.set_pty(pty) + + def get_original (self): + return self.console |