Ejemplo n.º 1
0
    def __init__(self, parent=None):
        super(FileBrowserDock, self).__init__(parent)

        self.initDock("File Browser")

        # make sure icons are loaded
        Icons.load()

        # self.openFunction = openFunc

        # tree view
        self.fileTree = widgets.FileSystemTreeView()
        self.fileTree.set_root_path(os.getcwd())
        self.contextMenu = FileBrowserMenu()
        self.fileTree.set_context_menu(self.contextMenu)

        # enable drag and drop
        self.fileTree.setDragEnabled(True)
        self.fileTree.setDragDropMode(
            QtWidgets.QAbstractItemView.DragDrop)
        self.fileTree.viewport().setAcceptDrops(True)
        self.fileTree.setDropIndicatorShown(True)
        # To Do -- not use a private member --
        self.fileTree._fs_model_source.setReadOnly(False)
        self.fileTree.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
        self.fileTree.setDefaultDropAction(QtCore.Qt.MoveAction)

        # Folder button
        self.menuHLayout = QtWidgets.QHBoxLayout()
        self.menuHLayout.setContentsMargins(1, 1, 1, 1)
        self.menuHLayout.addStretch(1)
        self.menuBtn = QtWidgets.QPushButton(Icons.folder, "...", self)
        self.menuBtn.setFlat(True)
        self.menuBtn.setStyleSheet("background-color: "
                                   "rgba(255, 255, 255, 0);")
        self.menuHLayout.addWidget(self.menuBtn)
        self.menuVLayout = QtWidgets.QVBoxLayout()
        self.menuVLayout.setContentsMargins(1, 1, 1, 1)
        self.menuVLayout.addLayout(self.menuHLayout)
        self.menuVLayout.addStretch(1)
        self.fileTree.setLayout(self.menuVLayout)

        self.dirContextMenu = DirMenu()
        self.menuBtn.setMenu(self.dirContextMenu)

        self.dirContextMenu.parentDirAction.triggered.connect(
            self.onParentDirClicked)
        self.dirContextMenu.openDirAction.triggered.connect(
            self.onOpenDirClicked)

        # add everything to the dock
        self.contents = QtWidgets.QWidget()
        self.layout = QtWidgets.QGridLayout(self.contents)
        self.layout.addWidget(self.fileTree, 0, 0, 1, 1)
        self.setWidget(self.contents)

        self.fileTree.doubleClicked.connect(self.onOpenItem)
        self.contextMenu.OpenAction.triggered.connect(self.openFile)
Ejemplo n.º 2
0
    def __init__(self, parent=None):
        super(FileBrowserDock, self).__init__(parent)

        self.initDock("File Browser")

        # make sure icons are loaded
        Icons.load()

        # self.openFunction = openFunc

        # tree view
        self.fileTree = widgets.FileSystemTreeView()
        self.fileTree.set_root_path(os.getcwd())
        self.contextMenu = FileBrowserMenu()
        self.fileTree.set_context_menu(self.contextMenu)

        # enable drag and drop
        self.fileTree.setDragEnabled(True)
        self.fileTree.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop)
        self.fileTree.viewport().setAcceptDrops(True)
        self.fileTree.setDropIndicatorShown(True)
        # To Do -- not use a private member --
        self.fileTree._fs_model_source.setReadOnly(False)
        self.fileTree.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
        self.fileTree.setDefaultDropAction(QtCore.Qt.MoveAction)

        # Folder button
        self.menuHLayout = QtWidgets.QHBoxLayout()
        self.menuHLayout.setContentsMargins(1, 1, 1, 1)
        self.menuHLayout.addStretch(1)
        self.menuBtn = QtWidgets.QPushButton(Icons.folder, "...", self)
        self.menuBtn.setFlat(True)
        self.menuBtn.setStyleSheet("background-color: "
                                   "rgba(255, 255, 255, 0);")
        self.menuHLayout.addWidget(self.menuBtn)
        self.menuVLayout = QtWidgets.QVBoxLayout()
        self.menuVLayout.setContentsMargins(1, 1, 1, 1)
        self.menuVLayout.addLayout(self.menuHLayout)
        self.menuVLayout.addStretch(1)
        self.fileTree.setLayout(self.menuVLayout)

        self.dirContextMenu = DirMenu()
        self.menuBtn.setMenu(self.dirContextMenu)

        self.dirContextMenu.parentDirAction.triggered.connect(
            self.onParentDirClicked)
        self.dirContextMenu.openDirAction.triggered.connect(
            self.onOpenDirClicked)

        # add everything to the dock
        self.contents = QtWidgets.QWidget()
        self.layout = QtWidgets.QGridLayout(self.contents)
        self.layout.addWidget(self.fileTree, 0, 0, 1, 1)
        self.setWidget(self.contents)

        self.fileTree.doubleClicked.connect(self.onOpenItem)
        self.contextMenu.OpenAction.triggered.connect(self.openFile)
Ejemplo n.º 3
0
    def display(self, desc, event):
        uri = desc.get_uri()
        if not gnomevfs.exists(uri):
            return
        file_info = gnomevfs.get_file_info(uri)
        is_dir = files.is_dir(file_info)
        icon_manager = Icons(self)
        if is_dir:
            pixbuf = icon_manager.retrieve_icon(u'stock_folder',
                                                gtk.STOCK_DIRECTORY)
            self.__appendMenuItem(label=menu0001, pixbuf=pixbuf,
                callback=lambda a: self.__set_repository(uri))
            pixbuf = None
        else:
            self.__appendMenuItem(stock=gtk.STOCK_OPEN,
                callback=lambda a: self.__open_file(uri))

        if is_dir:
            self.__appendSeperator()
            pixbuf = icon_manager.retrieve_icon(gtk.STOCK_NEW, gtk.STOCK_NEW)
            self.__appendMenuItem(label=menu0003, pixbuf=pixbuf,
                callback=lambda a: self.__create_file_in(uri))
            self.__appendMenuItem(label=menu0010, pixbuf=pixbuf,
                callback=lambda a: self.__create_folder_in(uri))
            self.__appendSeperator()
            pixbuf = None

            if gnomevfs.exists(uri) and uri.is_local:
                pixbuf = None
                if icon_manager.theme.has_icon(u'gnome-terminal'):
                    pixbuf = icon_manager.theme.load_icon(u'gnome-terminal',
                        16, gtk.ICON_LOOKUP_USE_BUILTIN)
                self.__appendMenuItem(label=menu0011, pixbuf=pixbuf,
                    callback=lambda a: self.__open_terminal(uri))
                pixbuf = icon_manager.retrieve_icon(u'stock_open',
                                                    gtk.STOCK_OPEN)
                self.__appendMenuItem(label=u'Browse...', pixbuf=pixbuf,
                    callback=lambda a: self.__open_file_browser(uri))
                self.__appendSeperator()
        self.__appendMenuItem(stock=gtk.STOCK_CUT, sensitive=False)
        self.__appendMenuItem(stock=gtk.STOCK_COPY, sensitive=False)
        if is_dir:
            self.__appendMenuItem(stock=gtk.STOCK_PASTE, sensitive=False)
        self.__appendSeperator()
        self.__appendMenuItem(menu0008, sensitive=False)
        self.__appendSeperator()
        self.__appendMenuItem(stock=gtk.STOCK_DELETE,
            callback=lambda a: self.__unlink(uri))
        pixbuf = None
        if icon_manager.theme.has_icon(u'gconf-editor'):
            pixbuf = icon_manager.theme.load_icon(u'gconf-editor',
                16, gtk.ICON_LOOKUP_USE_BUILTIN)
        self.__appendSeperator()
        self.__appendMenuItem(label=menu0002, pixbuf=pixbuf,
            callback=lambda a: self.__display_settings())
        pixbuf = None
        icon_manager = None
        self.popup(None, None, None, event.button, event.time)
Ejemplo n.º 4
0
 def update(self, info):
     """ Update icon """
     [volume, muted, var, card_name, mixer_name] = info
     vol = volume[0]
     if (muted):
         vol = 0
     icon = Icons.get_icon_name_by_volume(vol)
     self.set_from_icon_name(icon)
     
     #""" Update tooltip """
     tooltip = "<b>%s: %s%s </b>\n<small>%s: %s\n%s: %s</small>" % (
             _("Output"), Icons.get_volume_name(vol, muted),
             var, _("Card"), card_name,
             _("Mixer"), mixer_name)
     self.set_tooltip_markup(tooltip)
Ejemplo n.º 5
0
def main():

    urls = []
    debug = False

    if len(sys.argv) > 1:

        ##  If they want help
        if sys.argv[1] == "-h" or sys.argv[1] == "--help":
            print_help()
            return (0)

        elif sys.argv[1] == "-V" or sys.argv[1] == "--version":
            print_version()
            return (0)

        ##  If they're reading URLs from stdin
        elif sys.argv[1] == '-' or sys.argv[1] == "--stdin":
            rawUrls = sys.stdin.readlines()
            for r in rawUrls:
                urls.append(r.replace(' ', '\n', -1).strip())

        ##  If they're trying to use debug mode
        elif sys.argv[1] == "-d" or sys.argv[1] == "--debug":
            debug = True

        ##  If they're importing URLs
        elif os.path.exists(sys.argv[1]):
            try:

                fin = open(sys.argv[1], "r")
                rawUrls = fin.readlines()
                fin.close()

                for r in rawUrls:
                    urls.append(r.strip())

            except (OSError, PermissionError, FileNotFoundError):
                print("ERROR:  Cannot read from '%s'!  Aborting." %
                      sys.argv[1])
                sys.exit(1)

        ##  Running a bunch of URLs as args
        else:
            for arg in sys.argv[1:]:
                urls.append(arg)

    app = QApplication(sys.argv)

    sysInstall = (os.path.expanduser('~') in sys.argv[0])
    app.setWindowIcon(Icons().get_icon("application-icon", sysInstall))

    win = MainWindow(debug)
    if debug:
        print("(Debug mode)")

    if len(urls) > 0:
        win.load_urls(urls)

    sys.exit(app.exec_())
Ejemplo n.º 6
0
 def format(self, volume, muted, var, card_name, mixer_name):
     """ Format notification body """
     message = self.config.get(self.config.get_default_section(), "notify_body")
     volume = Icons.get_volume_name(volume, muted)
     message = message.replace('{volume}', '%s%s' % (volume, var))
     message = message.replace('{card}', '%s: %s' % (_("Card"), card_name))
     message = message.replace('{mixer}', '%s: %s' % (_("Mixer"), mixer_name))
     return message
Ejemplo n.º 7
0
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)
        self.setMaximumHeight(600)
        self.setMaximumWidth(800)
        self.icons = Icons()
        self.SettingsDialog = SettingsDialog(parent=self)
        self.NewProjectDialog = NewProjectDialog()

        self.connect_actions()
        self.connect_filetree()
        self.connect_icons()
        self._project_cache = {}
Ejemplo n.º 8
0
    def __init__(self, model: DataFrameModel,
                 df_manager: DataFrameModelManager, **kwargs):
        QtGui.QMainWindow.__init__(self, parent=kwargs.pop('parent', None))
        self.df_manager = df_manager
        self._widget = DataTableWidget()
        self._widget.setModel(model)

        kwargs['parent'] = self
        self.icons = Icons()
        self.setupUi(self)
        self.dialog_rename = None
        self.dialog_fields_edit = None
        self.connect_actions()
        self.connect_icons()
Ejemplo n.º 9
0
def main():

    urls = []
    if len(sys.argv) > 1:
        if sys.argv[1] == "-h" or sys.argv[1] == "--help":
            print_help()
            return (0)

    app = QApplication(sys.argv)

    app.setWindowIcon(Icons().get_icon("application-icon"))

    win = MainWindow()

    sys.exit(app.exec_())
Ejemplo n.º 10
0
    def init_UI(self):

        ##  Just to make life easier
        get_icon = Icons().get_icon

        ##  List of characters
        self.listWidget = QListWidget(self)

        ##  Add character button
        self.addChar = QPushButton(QIcon(get_icon("list-add")), "")
        self.addChar.setToolTip("Add a character")

        ##  Remove character button
        self.removeChar = QPushButton(QIcon(get_icon("list-remove")), "")
        self.removeChar.setToolTip("Remove selected character")

        ##  Bullshit to make qsplitter work
        self.list = MyListWidget(self)

        ##  Initial template
        self.template = self.parent.get_template()

        ##  Tab widget
        self.tabs = QTabWidget()

        self.load_tabs()

        ##  Tabs start out disabled
        self.tabs.setDisabled(True)

        ##  Connect it up
        self.connect_all()

        ##============= LAYOUTS

        splitter = QSplitter()
        splitter.addWidget(self.list)
        splitter.addWidget(self.tabs)

        splitter.setSizes([(WINDOW_WIDTH * .25), (WINDOW_WIDTH * .75)])

        ##  Set the layout
        hbox = QHBoxLayout()
        hbox.addWidget(splitter)
        self.setLayout(hbox)
Ejemplo n.º 11
0
 def show(self):
     """ Show the notification """
     if (not self.info):
         return
     
     duration = self.config.getfloat(self.config.get_default_section(), "notify_timeout")
     
     [volume, muted, var, card_name, mixer_name] = self.info
     volume = volume[0]
     icon = Icons.get_icon_name_by_volume(volume)
     
     body = self.format(volume, muted, var, card_name, mixer_name)
     hints = {"urgency": dbus.Byte(0), "desktop-entry": dbus.String("volti")}
     
     if self.config.getboolean(self.config.get_default_section(), "notify_position") and self.server_capable:
         hints["x"], hints["y"] = self.get_position()
         
     self.last_id = self.notify.Notify('volume', self.last_id, icon, self.title, body, [], hints, duration * 1000)
Ejemplo n.º 12
0
    def __init__(self, settings_ini: (str, SettingsINI)):
        self.df_manager = DataFrameModelManager()
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)
        self.icons = Icons()
        self.dialog_settings = SettingsDialog(settings=settings_ini)
        self.dialog_merge_purge = MergePurgeDialog(self.df_manager)
        self.dialog_export = DataFrameModelExportDialog(self.df_manager,
                                                        parent=self)
        self.dialog_import = CSVImportDialog(self)
        self.connect_window_title()
        self.connect_actions()
        self.connect_filetree()
        self.connect_icons()
        self.connect_settings_dialog()
        self.current_model = None

        # Temp cache
        self.df_windows = {}
Ejemplo n.º 13
0
    def init_UI(self):

        ##  Laziness
        get_icon = Icons().get_icon

        self.label = QLabel(self.path)
        self.pix = None
        self.iLabel = QLabel()

        self.btn = QPushButton(QIcon(get_icon("document-open")), "")
        self.btn.clicked.connect(self.get_image)

        hbox = QHBoxLayout()
        hbox.addWidget(self.btn)
        hbox.addWidget(self.label, 1)

        vbox = QVBoxLayout()
        vbox.addLayout(hbox)
        vbox.addWidget(self.iLabel)

        self.setLayout(vbox)
Ejemplo n.º 14
0
class Filechooser(gobject.GObject):
    __gtype_name__ = 'Filechooser'
    __gsignals__ = {
        'file-activated': (gobject.SIGNAL_RUN_FIRST, None, (str, )),
        'selection-changed': (gobject.SIGNAL_RUN_FIRST, None, (str, )),
        'filename-editing-started':
        (gobject.SIGNAL_RUN_FIRST, None, (object, )),
        'button-release-event': (gobject.SIGNAL_RUN_FIRST, None, ()),
        'error': (gobject.SIGNAL_RUN_FIRST, None, (str, str))
    }

    def __init__(self):

        gobject.GObject.__init__(self)

        # Glade setup
        self.builder = gtk.Builder()
        self.builder.add_from_file(os.path.join(UIDIR, "filechooser.glade"))
        self.builder.connect_signals(self)

        # Retrieve frequently used objects
        self.nav_box = self.builder.get_object('hbox1')
        self.eject_column = self.builder.get_object('eject_col')
        file_adj = self.builder.get_object('scrolledwindow1')
        self.file_vadj = file_adj.get_vadjustment()
        self.file_hadj = file_adj.get_hadjustment()

        # Retrieve data models
        self.file_liststore = self.builder.get_object("file_liststore")
        self.bookmark_liststore = self.builder.get_object("bookmark_liststore")

        # Retrieve treeviews
        self.file_treeview = self.builder.get_object("file_treeview")
        self.bookmark_treeview = self.builder.get_object("bookmark_treeview")

        self.bookmark_treeview.set_row_separator_func(self.bookmark_separator)

        # Enable DnD TODO DnD is not implemented yet
        self.file_treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, \
                                                    [('text/plain', 0, 0)], gtk.gdk.ACTION_MOVE | gtk.gdk.ACTION_COPY)
        self.file_treeview.enable_model_drag_dest([('text/plain', 0, 0)], \
                                                  gtk.gdk.ACTION_COPY)

        # Connect callbacks to VolumeMonitor
        self.mounts = gio.VolumeMonitor()
        self.mounts.connect('mount-added', self.on_mount_added)
        self.mounts.connect('mount-removed', self.on_mount_removed)

        # Initialize objects
        self.ok_cancel_dialog = Dialogs(DialogTypes.OK_CANCEL)
        self.bookmarks = BookMarks()
        self.icons = Icons(gtk.icon_theme_get_default())

        # Initialize places
        home = os.environ['HOME']
        desktop = os.path.expanduser("~/Desktop")
        self.places = [home, desktop]

        # Initialize variables
        self._cur_dir = desktop
        self._old_dir = " "
        self._filters = {}
        self._filter = ''
        self._files = []
        self._show_hidden = False
        self._hidden_exts = ['.desktop']
        self._copy = True
        self._selection = None
        self.nav_btn_list = []
        self.nav_btn_path_dict = {}

        # Initialize
        self._init_nav_buttons()

    # Have to do this once realized so sizes will have been allocated
    def on_vbox1_realize(self, widget):
        self._update_bookmarks()
        self._fill_file_liststore(self._cur_dir)

    def _init_nav_buttons(self):
        box = self.nav_box
        btn_list = self.nav_btn_list
        btn_dict = self.nav_btn_path_dict
        for i in range(10):
            btn = gtk.Button()
            btn.connect('clicked', self.on_nav_btn_clicked)
            btn.set_can_focus(False)
            btn.set_use_underline(False)
            btn_list.append(btn)
            box.pack_start(btn, False, False, 0)
            btn_dict[btn] = ''

    def _update_nav_buttons(self, path=None):
        if path is None:
            path = self._cur_dir
        places = path.split('/')[1:]
        path = '/'
        for btn in self.nav_btn_list:
            btn.hide()
        w_needed = 0
        for i, place in enumerate(places):
            btn = self.nav_btn_list[i]
            btn.set_label(place)
            path = os.path.join(path, place)
            self.nav_btn_path_dict[btn] = path
            btn.show()
            w_needed += btn.size_request()[0]
        w_allowed = self.nav_box.get_allocation()[2]
        if w_needed > w_allowed:
            self.builder.get_object('goto_root').hide()
            self.builder.get_object('arrow_left').show()
        else:
            self.builder.get_object('goto_root').show()
            self.builder.get_object('arrow_left').hide()
        count = 0
        while w_needed > w_allowed:
            btn = self.nav_btn_list[count]
            w_needed -= btn.size_request()[0]
            btn.hide()
            count += 1

    def on_nav_btn_clicked(self, widget, data=None):
        path = self.nav_btn_path_dict[widget]
        if path != self._cur_dir:
            self._fill_file_liststore(path)

    def on_goto_root_clicked(self, widget, data=None):
        self._fill_file_liststore('/')

    # HACK for now
    def on_arrow_left_clicked(self, widget, data=None):
        self.up_one_dir()

    def on_arrow_right_clicked(self, widget, data=None):
        pass

    def _fill_file_liststore(self, path=None):
        model = self.file_liststore
        model.clear()
        self.current_selection = None

        if path:
            self._cur_dir = path  #os.path.realpath(path)

            # Reset scrollbars since display has changed
            self.file_vadj.set_value(0)
            self.file_hadj.set_value(0)

        files = []
        folders = []
        if self._filter in self._filters:
            exts = self._filters[self._filter]
        else:
            exts = ''
        dirs = os.listdir(self._cur_dir)
        for obj in dirs:
            if obj[0] == '.' and not self._show_hidden:
                continue
            path = os.path.join(self._cur_dir, obj)
            if os.path.islink(path):
                path = os.readlink(path)
            if os.path.isdir(path):
                folders.append(obj)
            elif os.path.isfile(path):
                ext = os.path.splitext(obj)[1]
                if '*' in exts and not ext in self._hidden_exts:
                    files.append(obj)
                elif '*{0}'.format(ext) in exts:
                    files.append(obj)

        folders.sort(key=str.lower, reverse=False)
        for fname in folders:
            fpath = os.path.join(self._cur_dir, fname)
            icon = self.icons.get_for_directory(fpath)
            model.append([0, icon, fname, None, None])

        files.sort(key=str.lower, reverse=False)
        for fname in files:
            fpath = os.path.join(self._cur_dir, fname)
            icon = self.icons.get_for_file(fname)
            size, date = self._get_file_data(fpath)
            model.append([0, icon, fname, size, date])

        self._update_nav_buttons()

    def _get_file_data(self, fpath):
        size = os.path.getsize(fpath)
        if size >= 1E9:
            size_str = "{:.1f} GB".format(size / 1E9)
        elif size >= 1E6:
            size_str = "{:.1f} MB".format(size / 1E6)
        elif size >= 1E3:
            size_str = "{:.1f} KB".format(size / 1E3)
        else:
            size_str = "{} bytes".format(size)
        tstamp = os.path.getmtime(fpath)
        date_str = datetime.fromtimestamp(tstamp).strftime("%m/%d/%y %X")
        return size_str, date_str

    def on_select_toggled(self, widget, path):
        model = self.file_liststore
        model[path][0] = not model[path][0]

    def on_filechooser_treeview_cursor_changed(self, widget):
        path = widget.get_cursor()[0]
        # Prevent emiting selection changed on double click
        if path == self.current_selection:
            return
        self.current_selection = path
        fname = self.file_liststore[path][2]
        fpath = os.path.join(self._cur_dir, fname)
        self.emit('selection-changed', fpath)

    def on_filechooser_treeview_row_activated(self, widget, path, colobj):
        fname = self.file_liststore[path][2]
        fpath = os.path.join(self._cur_dir, fname)
        if os.path.isfile(fpath):
            self.emit('file-activated', fpath)
        elif os.path.isdir(fpath):
            self._fill_file_liststore(fpath)

    def on_file_name_editing_started(self, renderer, entry, row):
        self.emit('filename-editing-started', entry)

    def on_file_name_edited(self, widget, row, new_name):
        model = self.file_liststore
        old_name = model[row][2]
        old_path = os.path.join(self._cur_dir, old_name)
        new_path = os.path.join(self._cur_dir, new_name)
        if old_name == new_name:
            return
        if not os.path.exists(new_path):
            msg = "Renamed {} to {}".format(old_name, new_name)
            log.info(msg)
            self.info(msg)
            os.rename(old_path, new_path)
            model[row][2] = new_name
        else:
            msg = "Destination file already exists, won't rename"
            log.warning(msg)
            self.warn(msg)
            # TODO add overwrite confirmation dialog

    def on_file_treeview_button_release_event(self, widget, data=None):
        self.emit('button-release-event')

    # =======================================
    #   Methods to be called externally
    # =======================================

    # Get filechooser object to embed in main window
    def get_filechooser_widget(self):
        return self.builder.get_object('vbox1')

    # Add filter by name and list of extensions to display
    def add_filter(self, name, ext):
        self._filters[name] = ext

    # Delete filter by name
    def remove_filter(self, name):
        if name in self._filters:
            del self._filters[name]
            return True
        return False

    # Set current filter by name
    def set_filter(self, name):
        if name in self._filters:
            self._filter = name
            self._fill_file_liststore()
            return True
        return False

    # Get current filter
    def get_filter(self):
        if self._filter in self._filters:
            return [self._filter, self._filters[self._filter]]
        return None

    # Get names of all specified filters
    def get_filters(self):
        filters = []
        for filter in self._filters:
            filters.append(filter)
        return filters

    # Get whether hidden files are shown
    def get_show_hidden(self):
        return self._show_hidden

    # Set whether hidden files are shown
    def set_show_hidden(self, setting):
        self._show_hidden = setting

    # Get the path of the current display directory
    def get_current_folder(self):
        return self._cur_dir

    # Set current display directory to path
    def set_current_folder(self, fpath):
        if os.path.exists(fpath):
            self._fill_file_liststore(fpath)
            return True
        return False

    # Get absolute path at cursor
    def get_path_at_cursor(self):
        path = self.file_treeview.get_cursor()[0]
        if path is not None:
            fname = self.file_liststore[path][2]
            fpath = os.path.join(self._cur_dir, fname)
            return fpath
        return None

    # Set cursor at path
    def set_cursor_at_path(self, fpath):
        model = self.file_liststore
        tree = self.file_treeview
        if not os.path.exists(fpath):
            return False
        fpath, fname = os.path.split(fpath)
        if fpath != self._cur_dir:
            self._fill_file_liststore(fpath)
        for row in range(len(model)):
            if model[row][2] == fname:
                tree.set_cursor(row)
                return True
        return False

    # Get paths for selected
    def get_selected(self):
        model = self.file_liststore
        paths = []
        for row in range(len(model)):
            if model[row][0] == 1:
                fpath = os.path.join(self._cur_dir, model[row][2])
                paths.append(fpath)
        if len(paths) == 0:
            return None
        return paths

    # Check checkbox at file path
    def set_selected(self, fpath):
        model = self.file_liststore
        tree = self.file_treeview
        if not os.path.exists(fpath):
            return False
        fpath, fname = os.path.split(fpath)
        if fpath != self._cur_dir:
            self._fill_file_liststore(fpath)
        for row in range(len(model)):
            if model[row][2] == fname:
                model[row][0] = 1
                return True
        return False

    # Check all checkboxes in current display directory
    def select_all(self, fpath=None):
        model = self.file_liststore
        if fpath is not None:
            if os.path.isdir(fpath):
                self._fill_file_liststore(fpath)
            else:
                return False
        for row in range(len(model)):
            model[row][0] = 1
        return True

    # Uncheck all checkboxes in current display directory
    def unselect_all(self):
        model = self.file_liststore
        for row in range(len(model)):
            model[row][0] = 0

    # Get paths to current mounts
    def get_mounts(self):
        mounts = self.mounts.get_mounts()
        paths = []
        for mount in mounts:
            path = mount.get_root().get_path()
            paths.append(path)
        return paths

    # Get list of user bookmarks
    def get_bookmarks(self):
        return self.bookmarks.get()

    # Add bookmark
    def add_bookmark(self, path):
        if not path in self.places:
            self.bookmarks.add(path)
            self._update_bookmarks()

    # Remove bookmark
    def remove_bookmark(self, path):
        if not path in self.places:
            self.bookmarks.remove(path)
            self._update_bookmarks()

    # Clear all bookmarks
    def clear_bookmarks(self):
        self.bookmarks.clear()
        self._update_bookmarks()

    # Display parent of current directory
    def up_one_dir(self):
        path = os.path.dirname(self._cur_dir)
        self._fill_file_liststore(path)

    # Cut selected files
    def cut_selected(self):
        files = self.get_selected()
        if files is None:
            log.error("No files selected to cut")
            return False
        self._files = files
        self._copy = False
        log.debug("Files to cut: {}".format(files))
        return True

    # Copy selected files
    def copy_selected(self):
        files = self.get_selected()
        if files is None:
            log.error("No files selected to copy")
            return False
        self._files = files
        self._copy = True
        log.debug("Files to copy: {}".format(files))
        return True

    # Paste previously cut/copied files to current directory
    def paste(self):
        src_list = self._files
        if src_list is None:
            return False
        dst_dir = self._cur_dir
        if self._copy:
            for src in self._files:
                self._copy_file(src, dst_dir)
        elif not self._copy:
            for src in self._files:
                self._move_file(src, dst_dir)
            self._files = None
        self._fill_file_liststore()
        return True

    # Save file as, if path is specified it will be saved in that directory
    def save_as(self, path=None):
        model = self.file_liststore
        tree = self.file_treeview
        if path is None:
            path = self.get_selected()[0]
        if not os.path.exists(path) or path is None:
            return False
        fpath, fname = os.path.split(path)
        new_name = self._copy_file(path, fdir)
        for row in range(len(model)):
            if model[row][2] == new_name:
                break
        focus_column = self.builder.get_object('col_file_name')
        model[row][0] = 1
        tree.set_cursor(row, focus_column, True)

    # Create a new folder in the current directory
    def new_folder(self):
        model = self.file_liststore
        tree = self.file_treeview

        name = "New Folder"
        count = 1
        while os.path.exists(os.path.join(self._cur_dir, name)):
            name = 'New Folder {0}'.format(count)
            count += 1

        path = os.path.join(self._cur_dir, name)
        os.makedirs(path)
        self._fill_file_liststore()

        for row in range(len(model)):
            if model[row][2] == name:
                break
        focus_column = self.builder.get_object('col_file_name')
        model[row][0] = 1
        tree.set_cursor(row, focus_column, True)

    # Move selected files to trash (see file_util code at end)
    def delete_selected(self):
        paths = self.get_selected()
        if paths is None:
            return
        num = len(paths)
        for path in paths:
            info = move2trash(path)
        self._fill_file_liststore()

        # Show ERROR/INFO message at bottom of screen
        self.emit('error', info[0], info[1])

    # =======================================
    #   Drag and Drop TODO
    # =======================================

    def on_file_treeview_drag_begin(self, data, som):
        log.debug("drag {0} {1}".format(data, som))

    def on_file_treeview_drag_data_received(self):
        log.debug("got drag")

    def drag_data_received_cb(self, treeview, context, x, y, selection, info,
                              timestamp):
        drop_info = treeview.get_dest_row_at_pos(x, y)
        log.debug("got drag")
        if drop_info:
            model = treeview.get_model()
            path, position = drop_info
            data = selection.data
            # do something with the data and the model
            log.debug("{0} {1} {2}".format(model, path, data))
        return

    # =======================================
    #   Bookmark treeview
    # =======================================

    def on_mount_added(self, volume, mount):
        path = mount.get_root().get_path()
        name = os.path.split(path)[1]
        msg = 'External storage device "{}" mounted'.format(name)
        log.info(msg)
        self.info(msg)
        self._update_bookmarks()

    def on_mount_removed(self, volume, mount):
        path = mount.get_root().get_path()
        name = os.path.split(path)[1]
        msg = 'External storage device "{}" removed'.format(name)
        log.info(msg)
        self.info(msg)
        if self._cur_dir.startswith(path):
            self.file_liststore.clear()
            self._update_nav_buttons('')
        self._update_bookmarks()

    def on_bookmark_treeview_cursor_changed(self, widget):
        model = self.bookmark_liststore
        path, column = widget.get_cursor()
        fpath = model[path][2]
        if column == self.eject_column and model[path][3] == True:
            os.system('eject "{0}"'.format(fpath))
            if fpath == self._cur_dir:
                self.file_liststore.clear()
            return
        self._fill_file_liststore(fpath)

    def on_add_bookmark_button_release_event(self, widget, data=None):
        path = self.file_treeview.get_cursor()[0]
        if path is None:
            fpath = self._cur_dir
        else:
            fname = self.file_liststore[path][2]
            fpath = os.path.join(self._cur_dir, fname)
        if not os.path.isdir(fpath):
            return
        self.add_bookmark(fpath)

    def on_remove_bookmark_button_release_event(self, widget, data=None):
        path = self.bookmark_treeview.get_cursor()[0]
        if path is None:
            return
        fpath = self.bookmark_liststore[path][2]
        self.remove_bookmark(fpath)

    def _update_bookmarks(self):
        places = sorted(self.places, key=len, reverse=False)
        mounts = sorted(self.get_mounts(), key=self.sort, reverse=False)
        bookmarks = sorted(self.bookmarks.get(), key=self.sort, reverse=False)
        model = self.bookmark_liststore
        model.clear()

        # Add the places
        for path in places:
            name = os.path.split(path)[1]
            icon = self.icons.get_for_directory(path)
            model.append([icon, name, path, False])

        # Add the mounts
        for path in mounts:
            name = os.path.split(path)[1]
            icon = self.icons.get_for_device('USBdrive')
            model.append([icon, name, path, True])

        # Add the seperator
        model.append([None, None, None, False])

        # Add the bookmarks
        for bookmark in bookmarks:
            path, name = bookmark
            if not os.path.exists(path):
                continue
            if name == '':
                name = os.path.split(path)[1]
            icon = self.icons.get_for_directory(path)
            model.append([icon, name, path, False])

    # Generate sort key based on file basename
    def sort(self, path):
        return os.path.basename(path[0]).lower()

    # If name is None row should be a separator
    def bookmark_separator(self, model, iter):
        return self.bookmark_liststore.get_value(iter, 1) is None

    # =======================================
    #   File utilities
    # =======================================

    def _copy_file(self, src, dst_dir):
        src_dir, src_name = os.path.split(src)
        dst_name = src_name

        # find a unique copy name
        if src_dir == dst_dir:
            name, ext = os.path.splitext(dst_name)
            if '_copy' in name:
                name = name.rpartition('_copy')[0]

            count = 1
            while os.path.exists(os.path.join(dst_dir, dst_name)):
                dst_name = '{0}_copy{1}{2}'.format(name, count, ext)
                count += 1

        dst = os.path.join(dst_dir, dst_name)

        if os.path.exists(dst):
            text = "Destination already exists! \n Overwrite {}?".format(
                dst_name)
            overwrite = self.ok_cancel_dialog.run(text)
            if not overwrite:
                msg = "User selected not to overwrite {}".format(dst_name)
                log.info(msg)
                self.info(msg)
                return

        msg = 'Copying "{0}" to "{1}"'.format(src_name, dst_dir)
        log.info(msg)
        self.info(msg)

        if os.path.isfile(src):
            shutil.copy2(src, dst)

        else:
            shutil.copytree(src, dst)

        self._fill_file_liststore()
        return dst_name

    def _move_file(self, src, dst_dir):
        src_dir, src_name = os.path.split(src)

        if src_dir == dst_dir:
            msg = "MOVE ERROR: Source and destination are the same"
            log.error(msg)
            self.error(msg)
            return

        dst = os.path.join(dst_dir, src_name)

        if os.path.exists(dst):
            text = "Destination already exists! \n Overwrite {}?".format(
                src_name)
            overwrite = self.ok_cancel_dialog.run(text)
            if not overwrite:
                msg = 'User selected not to overwrite "{}"'.format(src_name)
                log.info(msg)
                self.info(msg)
                return

        msg = 'Moving "{0}" to "{1}"'.format(src_name, dst_dir)
        log.info(msg)
        self.info(msg)
        shutil.move(src, dst)

    # Shortcut methods to emit errors and print to terminal
    def error(self, text):
        self.emit('error', 'ERROR', text)

    def warn(self, text):
        self.emit('error', 'WARN', text)

    def info(self, text):
        self.emit('error', 'INFO', text)
Ejemplo n.º 15
0
class FileChooser(Gtk.Bin):
    __gtype_name__ = 'FileChooser'
    __gsignals__ = {
        'file-activated': (GObject.SignalFlags.RUN_FIRST, None, (str, )),
        'selection-changed': (GObject.SignalFlags.RUN_FIRST, None, (str, ))
    }

    def __init__(self, widget_window):
        Gtk.Bin.__init__(self)

        self.widget_window = widget_window

        # Glade setup
        self.builder = Gtk.Builder()
        self.builder.add_from_file(os.path.join(UIDIR, "filechooser.glade"))
        self.builder.connect_signals(self)

        self.builder.get_object = self.builder.get_object

        self.add(self.builder.get_object('filechooser'))

        # Retrieve frequently used objects
        self.nav_box = self.builder.get_object('nav_box')
        self.nav_btn_box = self.builder.get_object('nav_btn_box')

        file_adj = self.builder.get_object('fileview')
        self.file_vadj = file_adj.get_vadjustment()
        self.file_hadj = file_adj.get_hadjustment()

        # Retrieve data models
        self.file_liststore = self.builder.get_object("file_liststore")

        # Retrieve treeviews
        self.file_treeview = self.builder.get_object("file_treeview")
        self.bookmark_listbox = self.builder.get_object("bookmark_listbox")

        # Enable DnD ToDo implement DnD
        self.file_treeview.enable_model_drag_source(
            Gdk.ModifierType.BUTTON1_MASK, [('text/plain', 0, 0)],
            Gdk.DragAction.MOVE | Gdk.DragAction.COPY)
        self.file_treeview.enable_model_drag_dest([('text/plain', 0, 0)],
                                                  Gdk.DragAction.COPY)

        # Connect callbacks to VolumeMonitor
        self.mounts = Gio.VolumeMonitor.get()
        self.mounts.connect('mount-added', self.on_mount_added)
        self.mounts.connect('mount-removed', self.on_mount_removed)

        # Initialize helpers
        self.bookmarks = BookMarks()
        self.icons = Icons(Gtk.IconTheme.get_default())

        # Initialize places
        self.userdirs = UserDirectories()
        desktop = self.userdirs.get_XDG_directory('XDG_DESKTOP_DIR')
        home = self.userdirs.get_home_directory()
        self.places = [home, desktop]

        # Initialize variables
        self._cur_dir = None
        self._old_dir = ''
        self._filters = {}
        self._filter = None
        self._files = []
        self._show_hidden = False
        self._hidden_exts = ['.desktop']
        self._copy = True
        self._selection = None
        self.nav_btn_list = []
        self.nav_btn_path_dict = {}
        self.eject_btn_path_dict = {}

        # Initialize
        self._init_nav_buttons()

        self.show_all()

    # Have to do this once realized so sizes will have been allocated
    def on_filechooser_realize(self, widget):
        self._update_bookmarks()
        self._fill_file_liststore(self._cur_dir)

    def _init_nav_buttons(self):
        # FixMe this needs a lot of work. Try to copy this implementation
        # https://searchcode.com/codesearch/view/22668315/
        box = self.nav_btn_box
        box.get_style_context().add_class(Gtk.STYLE_CLASS_LINKED)

        arrow_left = Gtk.Arrow.new(Gtk.ArrowType.LEFT, Gtk.ShadowType.NONE)
        self.arrow_btn_left = Gtk.Button()
        self.arrow_btn_left.add(arrow_left)
        box.add(self.arrow_btn_left)

        self.btn_goto_root = Gtk.Button.new_from_icon_name(
            'gtk-harddisk', Gtk.IconSize.LARGE_TOOLBAR)
        self.btn_goto_root.connect('pressed', self.on_goto_root_clicked)
        box.add(self.btn_goto_root)

        btn_list = self.nav_btn_list
        btn_dict = self.nav_btn_path_dict
        for i in range(10):
            btn = Gtk.Button()
            btn.set_hexpand(False)
            btn.connect('clicked', self.on_nav_btn_clicked)
            btn.set_can_focus(False)
            btn.set_use_underline(False)
            btn_list.append(btn)
            box.add(btn)
            btn_dict[btn] = ''

#        arrow_right = Gtk.Arrow.new(Gtk.ArrowType.RIGHT, Gtk.ShadowType.NONE)
#        self.arrow_btn_right = Gtk.Button()
#        self.arrow_btn_right.add(arrow_right)
#        box.add(self.arrow_btn_right)

        box.show_all()

    def _update_nav_buttons(self, path=None):
        for btn in self.nav_btn_list:
            btn.hide()
        if path is None:
            path = self._cur_dir
        if len(path) == 1:
            return
        places = path.split('/')[1:]
        path = '/'
        w_needed = 0
        w_allowed = self.nav_btn_box.get_allocated_width()
        for i, place in enumerate(places):
            btn = self.nav_btn_list[i]
            btn.set_label(place)
            path = os.path.join(path, place)
            self.nav_btn_path_dict[btn] = path
            btn.show()
            w_needed += btn.get_allocated_width()
        if w_needed > w_allowed:
            self.btn_goto_root.hide()
            self.arrow_btn_left.show()
        else:
            self.btn_goto_root.show()
            self.arrow_btn_left.hide()
        count = 0
        while w_needed > w_allowed:
            btn = self.nav_btn_list[count]
            w_needed -= btn.get_allocated_width()
            btn.hide()
            count += 1

    def on_nav_btn_clicked(self, widget, data=None):
        path = self.nav_btn_path_dict[widget]
        if path != self._cur_dir:
            self._fill_file_liststore(path)

    def on_goto_root_clicked(self, widget, data=None):
        self._fill_file_liststore('/')

    # HACK for now
    def on_arrow_left_clicked(self, widget, data=None):
        self.up_one_dir()

    def on_arrow_right_clicked(self, widget, data=None):
        pass

    def _fill_file_liststore(self, path=None):
        model = self.file_liststore
        model.clear()
        self.selected_row = None

        if path:
            self._cur_dir = path
            # Reset scrollbars since display has changed
            self.file_vadj.set_value(0)
            self.file_hadj.set_value(0)
        if self._cur_dir is None:
            self._cur_dir = self.userdirs.get_XDG_directory('XDG_DESKTOP_DIR')

        files = []
        folders = []
        if self._filter:
            exts = self._filters[self._filter]
        else:
            exts = '*'  # Don't filter
        names = os.listdir(self._cur_dir)
        for name in names:
            if name[0] == '.' and not self._show_hidden:
                continue
            path = os.path.join(self._cur_dir, name)
            if os.path.islink(path):
                path = os.readlink(path)
            if os.path.isdir(path):
                folders.append(name)
            elif os.path.isfile(path):
                ext = os.path.splitext(name)[1]
                if '*' in exts or ext in exts and not ext in self._hidden_exts:
                    files.append(name)

        folders.sort(key=str.lower, reverse=False)
        for fname in folders:
            fpath = os.path.join(self._cur_dir, fname)
            icon = self.icons.get_for_directory(fpath)
            model.append([0, icon, fname, None, None])

        files.sort(key=str.lower, reverse=False)
        for fname in files:
            fpath = os.path.join(self._cur_dir, fname)
            icon = self.icons.get_for_file(fname)
            size, date = self._get_file_data(fpath)
            model.append([0, icon, fname, size, date])

        self._update_nav_buttons()

        self.emit('selection-changed', self._cur_dir)

        # If dir is in bookmarks, select the bookmark
        for row in self.bookmark_listbox.get_children():
            bookmark_path = row.get_tooltip_text()
            if bookmark_path == self._cur_dir:
                self.bookmark_listbox.select_row(row)
                break
        else:
            self.bookmark_listbox.unselect_all()

        # No file selected yet, so desensitize edit buttons
        self.builder.get_object('edit_button').set_sensitive(False)
        self.builder.get_object('cut_button').set_sensitive(False)
        self.builder.get_object('copy_button').set_sensitive(False)
        self.builder.get_object('delete_button').set_sensitive(False)

    def _get_file_data(self, fpath):
        size = os.path.getsize(fpath)
        if size >= 1E9:
            size_str = "{:.1f} GB".format(size / 1E9)
        elif size >= 1E6:
            size_str = "{:.1f} MB".format(size / 1E6)
        elif size >= 1E3:
            size_str = "{:.1f} KB".format(size / 1E3)
        else:
            size_str = "{} bytes".format(size)
        tstamp = os.path.getmtime(fpath)
        date_str = datetime.fromtimestamp(tstamp).strftime("%m/%d/%y %X")
        return size_str, date_str

    def count_lines(self, filename):
        lines = 0
        buf_size = 1024 * 1024
        with open(filename) as fh:
            read_f = fh.read
            buf = read_f(buf_size)
            while buf:
                lines += buf.count('\n')
                buf = read_f(buf_size)
        return lines + 1

    def on_select_toggled(self, widget, path):
        model = self.file_liststore
        model[path][0] = not model[path][0]

    def on_file_treeview_key_press_event(self, widget, event):
        kv = event.keyval
        # Events that don't need to know about modifiers
        if kv == Gdk.KEY_Escape:
            self.file_treeview.get_selection().unselect_all()
            self.builder.get_object('edit_button').set_sensitive(False)
            self.builder.get_object('cut_button').set_sensitive(False)
            self.builder.get_object('copy_button').set_sensitive(False)
            self.builder.get_object('delete_button').set_sensitive(False)
            return True
        elif kv == Gdk.KEY_Delete:
            self.delete_selected()
            return True
        elif kv == Gdk.KEY_F2:
            self.edit_selected()
            return True

        # Handle other events
        # Determine the actively pressed modifier
        modifier = event.get_state() & Gtk.accelerator_get_default_mod_mask()

        # Bool of Control or Shift modifier states
        control = modifier == Gdk.ModifierType.CONTROL_MASK
        shift = modifier == Gdk.ModifierType.SHIFT_MASK

        if control and kv == Gdk.KEY_c:
            return self.copy_selected()
        elif control and kv == Gdk.KEY_x:
            return self.cut_selected()
        elif control and kv == Gdk.KEY_v:
            return self.paste()

    def on_filechooser_treeview_cursor_changed(self, widget):
        row = widget.get_cursor()[0]
        # Prevent emitting selection changed on double click
        if row == self.selected_row or row is None:
            return

        self.selected_row = row

        fname = self.file_liststore[row][2]
        fpath = os.path.join(self._cur_dir, fname)
        self.emit('selection-changed', fpath)

        self.builder.get_object('edit_button').set_sensitive(True)
        self.builder.get_object('cut_button').set_sensitive(True)
        self.builder.get_object('copy_button').set_sensitive(True)
        self.builder.get_object('delete_button').set_sensitive(True)

    def on_filechooser_treeview_row_activated(self, widget, path, colobj):
        fname = self.file_liststore[path][2]
        fpath = os.path.join(self._cur_dir, fname)
        if os.path.isfile(fpath):
            self.emit('file-activated', fpath)
        elif os.path.isdir(fpath):
            self._fill_file_liststore(fpath)
        else:
            # If neither, probably does not exist, so reload
            self._fill_file_liststore()

    def on_file_name_editing_started(self, renderer, entry, row):
        keyboard.show(entry)

    def on_file_name_edited(self, widget, row, new_name):
        model = self.file_liststore
        model[row][0] = 0
        old_name = model[row][2]
        old_path = os.path.join(self._cur_dir, old_name)
        new_path = os.path.join(self._cur_dir, new_name)
        if old_name == new_name:
            return
        if not os.path.exists(new_path):
            os.rename(old_path, new_path)
            msg = 'Renamed "{}" to "{}"'.format(old_name, new_name)
            log.info(msg)
            self.widget_window.show_info(msg, 2)
            model[row][2] = new_name
        else:
            msg = "Destination file already exists, won't rename"
            log.warning(msg)
            self.widget_window.show_warning(msg)

    # =======================================
    #   Methods to be called externally
    # =======================================

    # Add filter by name
    def add_filter(self, name, exts):
        self._filters[name] = [ext.replace('*.', '.') for ext in exts]

    # Delete filter by name
    def delete_filter(self, name):
        if name in self._filters:
            del self._filters[name]
            if self._filter == name:
                self._filter = None
            return True
        return False

    # Set current filter by name
    def set_filter(self, name):
        if name is None:
            self._filter = None
        elif name in self._filters:
            self._filter = name
        self._fill_file_liststore()

    # Get current filter
    def get_filter(self):
        if self._filter in self._filters:
            return ['*' + ext for ext in self._filters[self._filter]]
        return None

    # Get names of all specified filters
    def get_filters(self):
        filters = []
        for filter in self._filters:
            filters.append(filter)
        return filters

    # Get whether hidden files are shown
    def get_show_hidden(self):
        return self._show_hidden

    # Set whether hidden files are shown
    def set_show_hidden(self, setting):
        self._show_hidden = setting

    # Get the path of the current display directory
    def get_current_folder(self):
        return self._cur_dir

    # Set current display directory to path
    def set_current_folder(self, fpath):
        #        fpath = fpath.rstrip('/')
        if os.path.exists(fpath):
            self._fill_file_liststore(fpath)
            log.info('Setting the current folder to "{}"'.format(fpath))
            return True
        log.error(
            'Can not set current folder to "{}", folder does not exist'.format(
                fpath))
        return False

    # Get absolute path at cursor
    def get_path_at_cursor(self):
        path = self.file_treeview.get_cursor()[0]
        if path is not None:
            fname = self.file_liststore[path][2]
            fpath = os.path.join(self._cur_dir, fname)
            return fpath
        return None

    # Set cursor at path
    def set_cursor_at_path(self, fpath):
        model = self.file_liststore
        tree = self.file_treeview
        if not os.path.exists(fpath):
            return False
        fpath, fname = os.path.split(fpath)
        if fpath != self._cur_dir:
            self._fill_file_liststore(fpath)
        for row in range(len(model)):
            if model[row][2] == fname:
                tree.set_cursor(row)
                return True
        return False

    # Get paths for selected
    def get_selected(self):
        model, rows = self.file_treeview.get_selection().get_selected_rows()
        if not rows:
            return
        paths = []
        for row in rows:
            fpath = os.path.join(self._cur_dir, model[row.to_string()][2])
            paths.append(fpath)
        return paths

    # Check checkbox at file path
    def set_selected(self, fpath):
        model = self.file_liststore
        tree = self.file_treeview
        if not os.path.exists(fpath):
            return False
        fpath, fname = os.path.split(fpath)
        if fpath != self._cur_dir:
            self._fill_file_liststore(fpath)
        for row in range(len(model)):
            if model[row][2] == fname:
                model[row][0] = 1
                return True
        return False

    # Check all checkboxes in current display directory
    def select_all(self, fpath=None):
        model = self.file_liststore
        if fpath is not None:
            if os.path.isdir(fpath):
                self._fill_file_liststore(fpath)
            else:
                return False
        for row in range(len(model)):
            model[row][0] = 1
        return True

    # Uncheck all checkboxes in current display directory
    def unselect_all(self):
        model = self.file_liststore
        for row in range(len(model)):
            model[row][0] = 0

    # Get paths to current mounts
    def get_mounts(self):
        mounts = self.mounts.get_mounts()
        paths = []
        for mount in mounts:
            path = mount.get_root().get_path()
            name = mount.get_name()
            paths.append([path, name, mount])
        return paths

    # Get list of user bookmarks
    def get_bookmarks(self):
        return self.bookmarks.get()

    # Add bookmark
    def add_bookmark(self, path):
        if not path in self.places:
            self.bookmarks.add(path)
            self._update_bookmarks()

    # Remove bookmark
    def remove_bookmark(self, path):
        if not path in self.places:
            self.bookmarks.remove(path)
            self._update_bookmarks()

    # Clear all bookmarks
    def clear_bookmarks(self):
        self.bookmarks.clear()
        self._update_bookmarks()

    # Display parent of current directory
    def up_one_dir(self):
        path = os.path.dirname(self._cur_dir)
        self._fill_file_liststore(path)

    # Cut selected files
    def cut_selected(self, widegt=None, data=None):
        files = self.get_selected()
        if not files:
            log.error("No files selected to cut")
            return False
        self._files = files
        self._copy = False
        log.debug("Files to cut: {}".format(files))
        self.builder.get_object('paste_button').set_sensitive(True)
        return True

    # Copy selected files
    def copy_selected(self, widegt=None, data=None):
        files = self.get_selected()
        if files is None:
            log.error("No files selected to copy")
            return False
        self._files = files
        self._copy = True
        log.debug("Files to copy: {}".format(files))
        self.builder.get_object('paste_button').set_sensitive(True)
        return True

    # Paste previously cut/copied files to current directory
    def paste(self, widegt=None, data=None):
        src_list = self._files
        if src_list is None:
            return False
        dst_dir = self._cur_dir
        if self._copy:
            for src in self._files:
                self._copy_file(src, dst_dir)
        elif not self._copy:
            for src in self._files:
                self._move_file(src, dst_dir)
            self._files = None
        self._fill_file_liststore()
        self.builder.get_object('paste_button').set_sensitive(False)
        return True

    # Save file as, if path is specified it will be saved in that directory
    def save_as(self, path=None):
        model = self.file_liststore
        tree = self.file_treeview
        if path is None:
            path = self.get_selected()[0]
        if not os.path.exists(path) or path is None:
            return False
        fpath, fname = os.path.split(path)
        new_name = self._copy_file(path, fdir)
        for row in range(len(model)):
            if model[row][2] == new_name:
                break
        focus_column = self.builder.get_object('col_file_name')
        model[row][0] = 1
        tree.set_cursor(row, focus_column, True)

    # Create a new folder in the current directory
    def new_folder(self, widegt=None, data=None):
        model = self.file_liststore
        tree = self.file_treeview

        name = "New Folder"
        count = 1
        while os.path.exists(os.path.join(self._cur_dir, name)):
            name = 'New Folder {0}'.format(count)
            count += 1

        path = os.path.join(self._cur_dir, name)
        os.makedirs(path)

        self._fill_file_liststore()

        for row in range(len(model)):
            if model[row][2] == name:
                break
        focus_column = self.builder.get_object('col_file_name')
        model[row][0] = 1
        tree.set_cursor(row, focus_column, True)

    # Create a new folder in the current directory
    def new_file(self, widegt=None, data=None):
        model = self.file_liststore
        tree = self.file_treeview

        name = "New file"
        count = 1
        while os.path.exists(os.path.join(self._cur_dir, name)):
            name = 'New Folder {0}'.format(count)
            count += 1

        path = os.path.join(self._cur_dir, name)
        with open(path, 'w') as fh:
            pass
        self._fill_file_liststore()

        for row in range(len(model)):
            if model[row][2] == name:
                break
        focus_column = self.builder.get_object('col_file_name')
        model[row][0] = 1
        tree.set_cursor(row, focus_column, True)

    def edit_selected(self, widget=None, data=None):
        row = self.file_treeview.get_cursor()[0]
        if not row:
            return
        model = self.file_liststore
        tree = self.file_treeview
        focus_column = self.builder.get_object('col_file_name')
        model[row][0] = 1
        tree.set_cursor(row, focus_column, True)

    # Move selected files to trash (see file_util code at end)
    def delete_selected(self, widegt=None, data=None):
        paths = self.get_selected()
        if paths is None:
            return
        num = len(paths)
        for path in paths:
            result, msg = move2trash(path)
        self._fill_file_liststore()

        if result == 'INFO':
            self.widget_window.show_info(msg, 2)
        else:
            self.widget_window.show_error(msg)

    # =======================================
    #   Drag and Drop TODO
    # =======================================

    def on_file_treeview_drag_begin(self, data, som):
        log.debug("drag {0} {1}".format(data, som))

    def on_file_treeview_drag_data_received(self):
        log.debug("got drag")

    def drag_data_received_cb(self, treeview, context, x, y, selection, info,
                              timestamp):
        drop_info = treeview.get_dest_row_at_pos(x, y)
        log.debug("got drag")
        if drop_info:
            model = treeview.get_model()
            path, position = drop_info
            data = selection.data
            # do something with the data and the model
            log.debug("{0} {1} {2}".format(model, path, data))
        return

    # =======================================
    #   Bookmark treeview
    # =======================================

    def on_mount_added(self, volume, mount):
        path = mount.get_root().get_path()
        name = os.path.split(path)[1]
        msg = 'External storage device "{}" mounted'.format(name)
        log.info(msg)
        self.widget_window.show_info(msg, 2)
        self._update_bookmarks()

    def on_mount_removed(self, volume, mount):
        path = mount.get_root().get_path()
        name = os.path.split(path)[1]
        msg = 'External storage device "{}" removed'.format(name)
        log.info(msg)
        self.widget_window.show_info(msg, 2)
        if self._cur_dir.startswith(path):
            self.file_liststore.clear()
            self._update_nav_buttons('')
        self._update_bookmarks()

    def on_eject_clicked(self, widget):
        mount = self.eject_btn_path_dict[widget]
        path = mount.get_root().get_path()
        name = mount.get_name()
        mount.eject(0, None, self.on_eject_finished)

    def on_eject_finished(self, mount, result):
        msg = 'Safe to remove external storage device "{}"'.format(
            mount.get_name())
        log.info(msg)
        self.widget_window.show_info(msg, 2)

    def on_add_bookmark_button_release_event(self, widget, data=None):
        path = self.file_treeview.get_cursor()[0]
        if path is None:
            fpath = self._cur_dir
        else:
            fname = self.file_liststore[path][2]
            fpath = os.path.join(self._cur_dir, fname)
        if not os.path.isdir(fpath):
            return
        self.add_bookmark(fpath)

    def on_remove_bookmark_button_release_event(self, widget, data=None):
        row = self.bookmark_listbox.get_selected_row()
        if row is None:
            return
        path = row.get_tooltip_text()
        self.bookmark_listbox.remove(row)
        self.bookmarks.remove(path)

    def _update_bookmarks(self):
        ext_media = sorted(self.get_mounts(), key=self.sort, reverse=False)
        bookmarks = sorted(self.bookmarks.get(), key=self.sort, reverse=False)

        for child in self.bookmark_listbox.get_children():
            self.bookmark_listbox.remove(child)

        # Add the places
        for path in self.places:
            icon = self.icons.get_for_directory(path)
            self.add_listbox_row(icon, path)

        # Add the mounts
        self.eject_btn_path_dict = {}
        icon = self.icons.get_for_device('USBdrive')
        for device in ext_media:
            path, name, mount = device
            if mount.can_eject():
                self.add_listbox_row(icon, path, name, mount)
            else:
                self.add_listbox_row(icon, path, name)

        # Add the seperator
        row = Gtk.ListBoxRow()
        row.set_selectable(False)
        separator = Gtk.Separator()
        row.add(separator)
        self.bookmark_listbox.add(row)

        # Add the bookmarks
        for bookmark in bookmarks:
            path, name = bookmark
            if not os.path.exists(path):
                continue
            icon = self.icons.get_for_directory(path)
            self.add_listbox_row(icon, path, name)

        self.bookmark_listbox.show_all()

    def add_listbox_row(self, icon, path, name=None, mount=None):
        if not name or name == '':
            name = os.path.split(path)[1]
        row = Gtk.ListBoxRow()
        row.set_tooltip_text(path)
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
        row.add(hbox)

        # Add icon
        image = Gtk.Image.new_from_pixbuf(icon)
        hbox.pack_start(image, False, False, 0)

        # Add label
        label = Gtk.Label()
        label.set_text(name)
        label.set_xalign(0)
        hbox.pack_start(label, True, True, 4)

        # Add media eject button
        if mount is not None:
            icon = self.icons.get_for_device('media-eject')
            image = Gtk.Image.new_from_pixbuf(icon)
            btn = Gtk.Button()
            self.eject_btn_path_dict[btn] = mount
            btn.connect('clicked', self.on_eject_clicked)
            btn.set_name('eject')
            btn.set_image(image)
            hbox.pack_start(btn, False, False, 0)

        self.bookmark_listbox.add(row)

    # Generate sort key based on file basename
    def sort(self, location):
        path = location[0]
        name = location[1]
        if name is None:
            return os.path.basename(path).lower()
        return name

    def on_bookmark_activated(self, widget, data=None):
        path = data.get_tooltip_text()
        self._fill_file_liststore(path)

    # =======================================
    #   File utilities
    # =======================================

    def _copy_file(self, src, dst_dir):
        src_dir, src_name = os.path.split(src)
        dst_name = src_name

        # find a unique copy name
        if src_dir == dst_dir:
            name, ext = os.path.splitext(dst_name)
            if '_copy' in name:
                name = name.rpartition('_copy')[0]

            count = 1
            while os.path.exists(os.path.join(dst_dir, dst_name)):
                dst_name = '{0}_copy{1}{2}'.format(name, count, ext)
                count += 1

        dst = os.path.join(dst_dir, dst_name)

        if os.path.exists(dst):
            text = "Destination already exists! \n Overwrite {}?".format(
                dst_name)
            overwrite = False  #self.ok_cancel_dialog.run(text)
            if not overwrite:
                msg = "User selected not to overwrite {}".format(dst_name)
                log.info(msg)
                self.widget_window.show_info(msg, 2)
                return

        if os.path.isfile(src):
            shutil.copy2(src, dst)

        else:
            shutil.copytree(src, dst)

        msg = 'Copied "{0}" to "{1}"'.format(src_name, dst_dir)
        log.info(msg)
        self.widget_window.show_info(msg, 2)

        self._fill_file_liststore()
        return dst_name

    def _move_file(self, src, dst_dir):
        src_dir, src_name = os.path.split(src)

        if src_dir == dst_dir:
            msg = "MOVE ERROR: Source and destination are the same"
            log.error(msg)
            self.widget_window.show_error(msg)
            return

        dst = os.path.join(dst_dir, src_name)

        if os.path.exists(dst):
            msg = "WARNING: Destination already exists. Overwrite {}?".format(
                src_name)
            overwrite = False  #self.ok_cancel_dialog.run(text)
            if not overwrite:
                msg = 'User selected not to overwrite "{}"'.format(src_name)
                log.info(msg)
                self.widget_window.show_info(msg, 2)
                return

        msg = 'Moving "{0}" to "{1}"'.format(src_name, dst_dir)
        log.info(msg)
        self.widget_window.show_info(msg, 2)
        shutil.move(src, dst)
Ejemplo n.º 16
0
    def __init__(self, widget_window):
        Gtk.Bin.__init__(self)

        self.widget_window = widget_window

        # Glade setup
        self.builder = Gtk.Builder()
        self.builder.add_from_file(os.path.join(UIDIR, "filechooser.glade"))
        self.builder.connect_signals(self)

        self.builder.get_object = self.builder.get_object

        self.add(self.builder.get_object('filechooser'))

        # Retrieve frequently used objects
        self.nav_box = self.builder.get_object('nav_box')
        self.nav_btn_box = self.builder.get_object('nav_btn_box')

        file_adj = self.builder.get_object('fileview')
        self.file_vadj = file_adj.get_vadjustment()
        self.file_hadj = file_adj.get_hadjustment()

        # Retrieve data models
        self.file_liststore = self.builder.get_object("file_liststore")

        # Retrieve treeviews
        self.file_treeview = self.builder.get_object("file_treeview")
        self.bookmark_listbox = self.builder.get_object("bookmark_listbox")

        # Enable DnD ToDo implement DnD
        self.file_treeview.enable_model_drag_source(
            Gdk.ModifierType.BUTTON1_MASK, [('text/plain', 0, 0)],
            Gdk.DragAction.MOVE | Gdk.DragAction.COPY)
        self.file_treeview.enable_model_drag_dest([('text/plain', 0, 0)],
                                                  Gdk.DragAction.COPY)

        # Connect callbacks to VolumeMonitor
        self.mounts = Gio.VolumeMonitor.get()
        self.mounts.connect('mount-added', self.on_mount_added)
        self.mounts.connect('mount-removed', self.on_mount_removed)

        # Initialize helpers
        self.bookmarks = BookMarks()
        self.icons = Icons(Gtk.IconTheme.get_default())

        # Initialize places
        self.userdirs = UserDirectories()
        desktop = self.userdirs.get_XDG_directory('XDG_DESKTOP_DIR')
        home = self.userdirs.get_home_directory()
        self.places = [home, desktop]

        # Initialize variables
        self._cur_dir = None
        self._old_dir = ''
        self._filters = {}
        self._filter = None
        self._files = []
        self._show_hidden = False
        self._hidden_exts = ['.desktop']
        self._copy = True
        self._selection = None
        self.nav_btn_list = []
        self.nav_btn_path_dict = {}
        self.eject_btn_path_dict = {}

        # Initialize
        self._init_nav_buttons()

        self.show_all()
Ejemplo n.º 17
0
    def __init__(self):

        gobject.GObject.__init__(self)

        # Glade setup
        self.builder = gtk.Builder()
        self.builder.add_from_file(os.path.join(UIDIR, "filechooser.glade"))
        self.builder.connect_signals(self)

        # Retrieve frequently used objects
        self.nav_box = self.builder.get_object('hbox1')
        self.eject_column = self.builder.get_object('eject_col')
        file_adj = self.builder.get_object('scrolledwindow1')
        self.file_vadj = file_adj.get_vadjustment()
        self.file_hadj = file_adj.get_hadjustment()

        # Retrieve data models
        self.file_liststore = self.builder.get_object("file_liststore")
        self.bookmark_liststore = self.builder.get_object("bookmark_liststore")

        # Retrieve treeviews
        self.file_treeview = self.builder.get_object("file_treeview")
        self.bookmark_treeview = self.builder.get_object("bookmark_treeview")

        self.bookmark_treeview.set_row_separator_func(self.bookmark_separator)

        # Enable DnD TODO DnD is not implemented yet
        self.file_treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, \
                                                    [('text/plain', 0, 0)], gtk.gdk.ACTION_MOVE | gtk.gdk.ACTION_COPY)
        self.file_treeview.enable_model_drag_dest([('text/plain', 0, 0)], \
                                                  gtk.gdk.ACTION_COPY)

        # Connect callbacks to VolumeMonitor
        self.mounts = gio.VolumeMonitor()
        self.mounts.connect('mount-added', self.on_mount_added)
        self.mounts.connect('mount-removed', self.on_mount_removed)

        # Initialize objects
        self.ok_cancel_dialog = Dialogs(DialogTypes.OK_CANCEL)
        self.bookmarks = BookMarks()
        self.icons = Icons(gtk.icon_theme_get_default())

        # Initialize places
        home = os.environ['HOME']
        desktop = os.path.expanduser("~/Desktop")
        self.places = [home, desktop]

        # Initialize variables
        self._cur_dir = desktop
        self._old_dir = " "
        self._filters = {}
        self._filter = ''
        self._files = []
        self._show_hidden = False
        self._hidden_exts = ['.desktop']
        self._copy = True
        self._selection = None
        self.nav_btn_list = []
        self.nav_btn_path_dict = {}

        # Initialize
        self._init_nav_buttons()
Ejemplo n.º 18
0
    def __init__(self, parent=None):
        super(MainMenuBar, self).__init__(parent)
        self.mainWindow = parent  # parent should be a MainWindow

        self.docks = []

        # sub-menus
        self.openRecMenu = \
            widgets.MenuRecentFiles(self,
                                    self.mainWindow.recent_files_manager)

        # must load icons here
        Icons.load()

        # Actions --
        # file actions
        self.newAct = QtWidgets.QAction(Icons.new, "&New", self)
        self.newAct.setShortcut('Ctrl+N')

        self.openAct = QtWidgets.QAction(Icons.openFile, "&Open", self)
        self.openAct.setShortcut('Ctrl+O')
        self.openRecAct = QtWidgets.QAction("Open &Recent", self)
        self.openRecAct.setMenu(self.openRecMenu)

        self.saveAct = QtWidgets.QAction(Icons.save, "&Save", self)
        self.saveAct.setShortcut('Ctrl+S')
        self.saveAsAct = QtWidgets.QAction(Icons.saveAs, "Save &As...", self)
        self.saveAsAct.setShortcut('Ctrl+Shift+S')
        self.saveAllAct = QtWidgets.QAction(Icons.saveAll, "Save A&ll", self)
        self.saveAllAct.setShortcut('Ctrl+Shift+A')

        self.closeAllAct = QtWidgets.QAction("Close All", self)

        self.exitAct = QtWidgets.QAction("E&xit", self)
        self.exitAct.setShortcut('Alt+F4')

        # tool actions
        self.interpAct = QtWidgets.QAction("&Interpreter Config...", self)
        self.runConfigAct = QtWidgets.QAction(Icons.runConfig,
                                              "Run &Config...", self)
        self.runAct = QtWidgets.QAction(Icons.run, "&Run", self)
        self.runAct.setShortcut('F5')

        # Top-level menus
        self.fileMenu = QtWidgets.QMenu("&File", self)
        self.fileMenu.addAction(self.newAct)
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.openRecAct)
        self.fileMenu.addAction(self.closeAllAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.saveAct)
        self.fileMenu.addAction(self.saveAsAct)
        self.fileMenu.addAction(self.saveAllAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.exitAct)
        self.addAction(self.fileMenu.menuAction())  # add to menubar

        self.editMenu = \
            QtWidgets.QMenu("&Edit", self)  # edit menu updated dynamically
        # self.editMenu.addActions(self.mainWindow.editor.actions())
        self.addAction(self.editMenu.menuAction())

        self.toolsMenu = QtWidgets.QMenu("&Tools", self)
        self.toolsMenu.addAction(self.interpAct)
        self.toolsMenu.addAction(self.runConfigAct)
        self.toolsMenu.addAction(self.runAct)
        self.toolsMenu.addSeparator()
        self.addAction(self.toolsMenu.menuAction())

        self.viewMenu = QtWidgets.QMenu("&View", self)
        self.addAction(self.viewMenu.menuAction())

        self.helpMenu = QtWidgets.QMenu("&Help", self)
        self.addAction(self.helpMenu.menuAction())
Ejemplo n.º 19
0
    def build_menu_bar(self):

        get_icon = Icons().get_icon

        ########  Actions

        ##  Save
        saveAction = QAction(QIcon(get_icon("document-save-as")), "&Save",
                             self)
        saveAction.setShortcut("Ctrl+S")
        saveAction.setStatusTip("Save file")
        saveAction.triggered.connect(self.save_file)

        ##  Save As
        saveAsAction = QAction(QIcon(get_icon("document-save")), "&Save As",
                               self)
        saveAsAction.setStatusTip("Save file as...")
        saveAsAction.triggered.connect(self.save_file_as)

        ##  Open
        openAction = QAction(QIcon(get_icon("document-open")), "&Open", self)
        openAction.setShortcut("Ctrl+O")
        openAction.setStatusTip("Open file")
        openAction.triggered.connect(self.open_file)

        ##  Import template
        importAction = QAction(QIcon(get_icon("document-open")),
                               "&Import template", self)
        importAction.setStatusTip("Import a template file")
        importAction.triggered.connect(self.import_template)

        ##  Export
        exportAction = QAction(QIcon(get_icon("document-save")), "&Export PDF",
                               self)
        exportAction.setShortcut("Ctrl+E")
        exportAction.setStatusTip("Export each character's profile as a PDF")
        exportAction.triggered.connect(self.export_file)
        if not canExportPDF:
            exportAction.setDisabled(True)

        ##  Exit
        exitAction = QAction(QIcon(get_icon("application-exit")), "&Exit",
                             self)
        exitAction.setShortcut("Ctrl+Q")
        exitAction.setStatusTip("Exit the application")
        exitAction.triggered.connect(qApp.quit)

        ##  About action
        aboutAction = QAction(QIcon(get_icon("help-about")), "&About", self)
        aboutAction.setStatusTip("Information about the program")
        aboutAction.triggered.connect(self.about)

        ##  Create the menubar
        menuBar = self.menuBar()

        ##  Create file menu
        fileMenu = menuBar.addMenu("&File")
        fileMenu.addAction(openAction)

        ##  Recents menu
        self.recentsMenu = fileMenu.addMenu("Recent")

        fileMenu.addSeparator()
        fileMenu.addAction(saveAction)
        fileMenu.addAction(saveAsAction)
        fileMenu.addSeparator()
        fileMenu.addAction(exportAction)
        fileMenu.addSeparator()
        fileMenu.addAction(exitAction)

        ##  Create edit menu
        editMenu = menuBar.addMenu("&Edit")
        editMenu.addAction(importAction)

        helpMenu = menuBar.addMenu("&Help")
        helpMenu.addAction(aboutAction)

        self.load_recents_menu()
Ejemplo n.º 20
0
from flask import Flask
from flask import Response
from sense_hat import SenseHat
from icons import Icons
import json

app = Flask(__name__)
sense = SenseHat()
icons = Icons()

# My sense is upside down for reasons of cable.
sense.set_rotation(180)

@app.route('/temperator', methods=['GET'])
def temperature():
  r = {'temperature': sense.get_temperature()}
  return Response(json.dumps(r), mimetype='application/json')


@app.route('/humidity', methods=['GET'])
def humidity():
  r = {'humidity': sense.get_humidity()}
  return Response(json.dumps(r), mimetype='application/json')

@app.route('/pressure', methods=['GET'])
def humidity():
  r = {'pressure': sense.get_pressure()}
  return Response(json.dumps(r), mimetype='application/json')

@app.route('/emotion' methods=['POST'])
def emotion():
Ejemplo n.º 21
0
class ProjectTreeView(gtk.TreeView):
    """A widget for displaying the files within a repositoy."""

    def __init__(self):
        """Constructor.
        Creates the initial view of the project repository."""
        super(ProjectTreeView, self).__init__()
        self.__current_repository = None
        self.__activate_file = None
        self.__refresh = None
        self.__settings = Settings()
        self.__initialize_treeview()
        self.__initialize_icons()
        self.__initialize_columns()

    def set_activate_file(self, afile=None):
        """Sets the method to use when activating a file."""
        if afile is not None and not callable(afile):
            raise ValueError, err0010
        self.__activate_file = afile

    def set_refresh(self, refresh=None):
        """Sets the method to use when refreshing."""
        if refresh is not None and not callable(refresh):
            raise ValueError, err0011
        self.__refresh = refresh

    def get_repository(self):
        """Gets the URI associated with the currently opened repository."""
        return self.__current_repository

    def refresh(self):
        """Refreshes the current view."""
        current_repo = self.get_repository()
        # Check to be sure we have a current repository
        if current_repo is not None:
            # Collection to hold all expanded rows
            open_paths = []
            # Append all the expanded paths to the collection
            self.map_expanded_rows(self.__map_expanded_rows, open_paths)
            self.__refresh()
            # Expand all previously expanded paths
            path_iter = self.get_model().get_iter_root()
            self.__expand_previously_open_rows(path_iter, open_paths)
            del open_paths[0:]

            self.queue_draw()

    def set_repository(self, uri):
        """Sets the repository to be viewed.

        @param uri: The URI to set the repository to.
        @type uri: a gnomevfs.URI

        """
        self.__current_repository = uri

        self.get_model().clear()

        # Create the root directory within the list
        parent_dir = self.__append_descriptor(uri, True, None)

        # Be sure there is a loading item within the current directory
        self.__append_loading_cell(parent_dir)

        # Expand the current directory to show the rest of the files
        iterpath = self.get_model().get_path(parent_dir)
        self.expand_row(iterpath, False)

        self.queue_draw()

    def __expand_previously_open_rows(self, path_iter, open_paths):
        """Expands any previously opened paths after a refresh."""
        while path_iter is not None:
            desc = self.get_model().get_value(path_iter, 0)

            # Be sure we have a PathDescriptor
            if isinstance(desc, PathDescriptor):
                # If the path was previously opened open it
                if desc.get_uri() in open_paths:
                    path = self.get_model().get_path(path_iter)
                    self.expand_row(path, False)

                    # Remove it from the list
                    open_paths.remove(desc.get_uri())

                # If the iterator has children, check to see if any should
                # be open
                if self.get_model().iter_has_child(path_iter):
                    child = self.get_model().iter_nth_child(path_iter, 0)
                    self.__expand_previously_open_rows(child, open_paths)

            # Move to the next row
            path_iter = self.get_model().iter_next(path_iter)

    def __map_expanded_rows(self, widget, path, data):
        """Store previously opened paths."""
        # Append URI values to track what is open
        path_iter = self.get_model().get_iter(path)

        if path_iter is not None:
            desc = self.get_model().get_value(path_iter, 0)

            if isinstance(desc, PathDescriptor):
                data.append(desc.get_uri())

    def __initialize_treeview(self):
        """Create the view and set its properties."""
        treestore = gtk.TreeStore(object, gtk.gdk.Pixbuf, gtk.gdk.Pixbuf)

        self.set_property(u'model', treestore)
        self.set_property(u'enable-search', False)
        self.set_property(u'headers-visible', False)

        self.connect(u'test-expand-row', self.__on_expand_row)
        self.connect(u'row-activated', self.__on_row_activated)
        self.connect(u'row-collapsed', self.__on_collapse_row)

    def __initialize_columns(self):
        """Creates the columns for the view."""
        # Create the necessary widgets for the view
        image_renderer = gtk.CellRendererPixbuf()
        name_renderer = gtk.CellRendererText()
        column = gtk.TreeViewColumn()

        # Pach the icon renderer and the text label renderer into the view
        column.pack_start(image_renderer, False)
        column.pack_start(name_renderer, True)

        # Set the icons for the icon renderer
        column.set_attributes(image_renderer, pixbuf=1, pixbuf_expander_open=2,
                              pixbuf_expander_closed=1)

        # Set the texit labels method for retrieving the file's name
        column.set_cell_data_func(name_renderer, self.__retrieve_filename)

        self.append_column(column)

    def __initialize_icons(self):
        """Retrieves the icons needed to display within the file view."""
        self.__icons = Icons(self)

    def __populate_directory(self, uri, parent=None):
        """Populates the directory list alphabetically by directory then by
        file.

        @param uri: the URI of the directory.
        @type uri: a gnomevfs.URI

        @param parent: the parent iterator to append the child to.
        @type parent: a gtk.TreeIter
        """
        # Retrieve directories alphabetically
        directory = gnomevfs.DirectoryHandle(uri)
        file_filter = self.__settings.get_file_filter()
        show_file = None

        if len(file_filter) > 0:
            comp = re.compile(file_filter)

            def __show_file(file_name):
                if comp.search(file_name) is not None:
                    return True

                return False

            show_file = __show_file

        for file_info in sorted(directory, cmp=self.__compare_files):
            # Process folders
            if files.is_visible_dir(file_info):
                file_uri = uri.append_file_name(file_info.name)

                cur_dir = self.__append_descriptor(file_uri, True, parent)
                self.__append_loading_cell(cur_dir)

            # Process Files
            elif files.is_visible_file(file_info):
                if show_file is not None and not show_file(file_info.name):
                    continue

                file_uri = uri.append_file_name(file_info.name)

                self.__append_descriptor(file_uri, False, parent)

    def __compare_files(self, file_a, file_b):
        """Compares to files and determines which is first based on file type
        and file name."""
        type_a = file_a.type
        type_b = file_b.type

        # Make folders the most important in the list
        if type_a == gnomevfs.FILE_TYPE_DIRECTORY: type_a = 0
        else: type_a = 1

        if type_b == gnomevfs.FILE_TYPE_DIRECTORY: type_b = 0
        else: type_b = 1

        type_comp = cmp(type_a, type_b)

        # If the files are the same type then compare names
        if type_comp == 0:
            return cmp(file_a.name, file_b.name)

        return type_comp

    def __empty_directory(self, iterator):
        """Removes all the items within a directory on the tree."""
        model = self.get_model()

        # Remove each of the child nodes within the iterator
        while model.iter_has_child(iterator):
            child = model.iter_nth_child(iterator, 0)
            model.remove(child)

    def __append_descriptor(self, uri, is_dir, parent):
        """Creates a tree node with a path descriptor."""
        open_icon = None
        default_icon = None

        # Retrieve a default and open icon if the URI is a folder, otherwise
        # just a default icon
        if is_dir:
            open_icon = self.__icons.folder_open
            default_icon = self.__icons.folder
        else:
            default_icon = self.__icons.retrieve_file_icon(str(uri))

        # Create a descriptor and append a new node that represents that
        # descriptor into the tree
        desc = PathDescriptor(uri, is_dir)
        parent_dir = self.get_model().append(parent, [desc, default_icon,
                                                      open_icon])

        # Attach the corresponding tree iterator to the descriptor
        desc.set_iter(parent_dir)

        return parent_dir

    def __append_empty_cell(self, iterator):
        """Creates an 'empty' cell within the tree."""
        self.get_model().append(iterator, [msg0003, None, None])

    def __append_loading_cell(self, iterator):
        """Creates a 'loading' cell within the tree."""
        self.get_model().append(iterator, [msg0002, None, None])

    def __retrieve_filename(self, column, cell, model, iterator):
        """Retrieves the filename of the PathDescriptor."""
        desc = model.get_value(iterator, 0)

        # Retrieve the filename of the PathDescriptor or string.
        if isinstance(desc, PathDescriptor):
            cell.set_property(u'text', desc.get_name())
        else:
            cell.set_property(u'text', desc)

    def __on_expand_row(self, widget, iterator, path, data=None):
        """Empties a directory then loads in the files."""
        if iterator is not None:
            desc = self.get_model().get_value(iterator, 0)

            if not isinstance(desc, PathDescriptor):
                return

            # If the object is a directory clear its contents within the tree
            # and rescan it
            if desc.is_dir():
                self.freeze_child_notify()

                # Empty the directory
                self.__empty_directory(iterator)

                self.__populate_directory(desc.get_uri(), iterator)

                # Append an "Empty" cell if the directory is empty
                if not self.get_model().iter_has_child(iterator):
                    self.__append_empty_cell(iterator)

                self.thaw_child_notify()
                self.queue_draw()

    def __on_collapse_row(self, widget, iterator, path, data=None):
        """Empties a directory to conserve memory."""
        if iterator is not None:
            desc = self.get_model().get_value(iterator, 0)

            if not isinstance(desc, PathDescriptor):
                return

            # If the object is a directory clear its contents within the tree
            # and rescan it
            if desc.is_dir():
                self.freeze_child_notify()

                # Empty the directory
                self.__empty_directory(iterator)

                # Append a loading node to be used later when expanding
                self.__append_loading_cell(iterator)

                self.thaw_child_notify()
                self.queue_draw()

    def __on_row_activated(self, widget, path, view_column, data=None):
        """Enters a directory or loads a file."""
        iterator = self.get_model().get_iter(path)

        if iterator is not None:
            desc = self.get_model().get_value(iterator, 0)

            # Be sure we hane a PathDescriptor before we try to activate the
            # node.
            if not isinstance(desc, PathDescriptor):
                return

            # Expand or collapse a directory
            if desc.is_dir():
                if self.row_expanded(path):
                    self.collapse_row(path)
                else:
                    self.expand_row(path, False)

            # Activate the file
            else:
                if self.__activate_file is not None:
                    self.__activate_file(desc)

            self.queue_draw()
Ejemplo n.º 22
0
class Collection():
    # These values represent the root menu items. It is important, because
    # the queries may be different, depending on the values. These values
    # also appear in the URL-s (part of the server API) as is.
    COLLECTIONTYPE_PLACE_OF_USAGE_ID = "0"
    COLLECTIONTYPE_USER_GROUPS_ID = "1"
    COLLECTIONTYPE_AREA_OF_USAGE_ID = "2"

    IconDB = Icons()

    def executeRawQuery(
        self, objects, queryString, include=[], summaryMenu=[], converters={}
    ):
        data = []
        result = objects.raw(queryString)

        for p in result:
            subset = []

            if summaryMenu:
                subset.extend(summaryMenu)
                subset.append(["new_section"])

            for column_name in include:
                s1 = unicode(column_name, errors='replace')
                s2 = getattr(p, column_name)

                if type(s2) is str:
                    s2 = s2.decode("windows-1250")
                elif type(s2) is decimal.Decimal:
                    s2 = str(s2)

                if column_name in converters.keys():
                    s2 = converters[column_name](str(s2).strip())

                subset.append([s1, "", s2])

            data.append(subset)

        return {
            "desc": self.desc,
            "data": data
        }

    def getAttr(self, p, field):
        attr = getattr(p, field)
        return attr if attr else 0

    def generateTemperatureString(self, tableId, temperatureField):
        return '%s."%s"' % (tableId, temperatureField)

    def generateParentString(self, node):
        parentStr = ""

        for i in range(0, 9):
            parentStr += '("parent%d"=%s) or ' % (i, node)

        return parentStr

    def getActualField(self, set, attrName):
        for line in set:
            if line[0] == attrName:
                return line[2]

    def removeField(self, set, attrName):
        for line in set:
            if line[0] == attrName:
                set.remove(line)
                continue

    def draw(self, axisDesc, results, title_id, ylimit=None):
        dateAxis = []
        # In the database, dt_num is a Delphi/float representation of the dates, starting point is 1899.12.30 0:0:0. Python datetime calculates with starting point 1.1.1 0:0:0. This magic number is teh fload difference of the two.
        delphiStartDate = datetime.date(1899, 12, 30)
        dataAxises = [[]] + list(repeat([], len(axisDesc)))

        if not len(list(results)):
            return {
                "desc": self.desc,
                "data": []
            }

        for p in results:
            date = datetime.timedelta(self.getAttr(p, "dt_num")) + delphiStartDate

            dateAxis.append(date)

            for i in range(0, len(axisDesc)):
                dataAxises[i].append(self.getAttr(p, axisDesc[i]["column"]))
                dataAxises[i]

        fig = plt.figure()

        for i in range(0, len(axisDesc)):
            plt.plot_date(dateAxis, dataAxises[i], axisDesc[i]["line"], label=axisDesc[i]["label"], fillstyle='full')

        if ylimit:
            ax = plt.subplot(111)
            ax.set_ylim(ylimit)

        plt.legend()
        # Tweak spacing to prevent clipping of ylabel
        fig.autofmt_xdate()
        output = StringIO.StringIO()
        plt.savefig(output, format='png', orientation='landscape')
        im_data = output.getvalue()
        data = [["", base64.b64encode(im_data)]]

        return {
            "desc": self.desc,
            "data": [data]
        }

    def getLabels(self, column, language, isMetric="1"):
        columnTranslated = column

        if language == "hu":
            if column == "ua_l":
                columnTranslated = "készlet, " + ("liter " if isMetric == "1" else "gallon")
            elif column == "ua_l15":
                columnTranslated = "készlet, " + ("liter, 15˚C" if isMetric == "1" else "gallon, 58˚F")
            elif column == "hofok":
                columnTranslated = "höfok, " + ("˚C" if isMetric == "1" else "˚F")
            elif column == "h2o_mm":
                columnTranslated = "víz magasság, mm"
            elif column == "szazalek":
                columnTranslated = "százalék"
            elif column == "hiba":
                columnTranslated = "hibaszám"
        if language == "en":
            if column == "ua_l":
                columnTranslated = "inventory, " + ("liter " if isMetric == "1" else "gallon")
            elif column == "ua_l15":
                columnTranslated = "inventory, " + ("liter, 15˚C" if isMetric == "1" else "gallon, 58˚F")
            elif column == "hofok":
                columnTranslated = "temperature, " + ("˚C" if isMetric == "1" else "˚F")
            elif column == "h2o_mm":
                columnTranslated = "water level, mm"
            elif column == "szazalek":
                columnTranslated = "percentage"
            elif column == "hiba":
                columnTranslated = "error number"

        return columnTranslated

    def parseDbGrid(self, grid):
        p = re.compile('FieldName..(\w*)')
        return p.findall(grid)

    def getParent(self, node):
        return TreenodeModel.objects.get(dbindx=node).parent0

    def getFieldsFromDBGrid(self, node, username, tabId):
        try:
            obj = Dbgrid.objects.get(user=username, node=node, ful_n=tabId)
        except Dbgrid.DoesNotExist:
            parent = self.getParent(node)

            if parent:
                return self.getFieldsFromDBGrid(parent.dbindx, username, tabId)
            else:
                return {
                    "order_by": "",
                    "fields": []
                }

        fields = self.parseDbGrid(obj.grid)

        return {
            "order_by": obj.sorrend,
            "fields": fields
        }

    @staticmethod
    def FuelTypeConverter(t):
        if t == "1":
            return "E95"
        elif t == "2":
            return "Diesel"
        elif t == "3":
            return "Jet"

        return t
Ejemplo n.º 23
0
    def build_menu_bar(self):

        get_icon = Icons().get_icon

        ##  Is this a system install?
        sysInstall = (os.path.expanduser('~') in sys.argv[0])

        ########  Actions

        ##  Save
        saveAction = QAction(
            QIcon(get_icon("document-save-symbolic", sysInstall)),
            "&Save Settings", self)
        saveAction.setShortcut("Ctrl+S")
        saveAction.setStatusTip("Save current settings")
        saveAction.triggered.connect(self.save_settings)

        ##  Import playlist
        importAction = QAction(
            QIcon(get_icon("document-open-symbolic", sysInstall)),
            "&Import URLs", self)
        importAction.setShortcut("Ctrl+I")
        importAction.setStatusTip("Import a saved list of URLs")
        importAction.triggered.connect(self.import_urls)

        ##  Export playlist
        exportAction = QAction(
            QIcon(get_icon("document-save-symbolic", sysInstall)),
            "&Export URLs", self)
        exportAction.setShortcut("Ctrl+E")
        exportAction.setStatusTip("Export URLs to a text file")
        exportAction.triggered.connect(self.export_urls)

        ##  Exit
        exitAction = QAction(
            QIcon(get_icon("application-exit-symbolic", sysInstall)), "&Exit",
            self)
        exitAction.setShortcut("Ctrl+Q")
        exitAction.setStatusTip("Exit the application")
        exitAction.triggered.connect(qApp.quit)

        ##  Go
        goAction = QAction(QIcon(get_icon("go-next-symbolic", sysInstall)),
                           "Download URLs", self)
        goAction.setShortcut("Return")
        goAction.setStatusTip("Download current URL list")
        goAction.triggered.connect(self.mainWidget.start_download)

        ##  Paste
        pasteAction = QAction(
            QIcon(get_icon("edit-paste-symbolic", sysInstall)), "&Paste", self)
        pasteAction.setShortcut("Ctrl+V")
        pasteAction.setStatusTip("Add URL from clipboard")
        pasteAction.triggered.connect(self.mainWidget.quick_add_item)

        ##  Set destination
        setDestAction = QAction(
            QIcon(get_icon("document-open-symbolic", sysInstall)),
            "Set &Download directory", self)
        setDestAction.setShortcut("Ctrl+D")
        setDestAction.setStatusTip("Choose your download directory")
        setDestAction.triggered.connect(self.mainWidget.set_destination)

        ##  Allow duplicates
        self.dupeAction = QAction("Allow duplicates", self)
        self.dupeAction.setStatusTip("Allow duplicate URLs in queue")
        self.dupeAction.setCheckable(True)
        if self.opts["duplicates"] == "true":
            self.dupeAction.setChecked(True)
        self.dupeAction.triggered.connect(self.check_dupe_box)

        ##  New folder for playlists
        self.playlistFolderAction = QAction("New folder for playlists", self)
        self.playlistFolderAction.setStatusTip(
            "Create a new folder for every playlist downloaded")
        self.playlistFolderAction.setCheckable(True)
        if self.opts["playlistFolder"] == "true":
            self.playlistFolderAction.setChecked(True)
        self.playlistFolderAction.triggered.connect(
            self.check_playlist_dir_box)

        ##  About action
        aboutAction = QAction(
            QIcon(get_icon("help-about-symbolic", sysInstall)), "&About", self)
        aboutAction.setStatusTip("Information about the program")
        aboutAction.triggered.connect(self.about)

        ##  ======  Theme actions
        ##  System default theme
        defaultThemeAction = QAction("Default", self)
        defaultThemeAction.setStatusTip("Set theme to system default")
        defaultThemeAction.triggered.connect(self.toggle_theme_default)

        ##  Light theme
        lightThemeAction = QAction("Light theme", self)
        lightThemeAction.setStatusTip("Use a light theme")
        lightThemeAction.triggered.connect(self.toggle_theme_light)

        ##  Dark theme
        darkThemeAction = QAction("Dark theme", self)
        darkThemeAction.setStatusTip("Use a dark theme")
        darkThemeAction.triggered.connect(self.toggle_theme_dark)

        ##  Create the menubar
        menuBar = self.menuBar()

        ##  Create file menu
        fileMenu = menuBar.addMenu("&File")
        fileMenu.addAction(saveAction)
        fileMenu.addAction(exportAction)
        fileMenu.addSeparator()
        fileMenu.addAction(importAction)
        fileMenu.addSeparator()
        fileMenu.addAction(goAction)
        fileMenu.addSeparator()
        fileMenu.addAction(exitAction)

        ##  Edit Menu
        editMenu = menuBar.addMenu("&Edit")
        editMenu.addAction(pasteAction)

        ##  Settins Menu
        settingsMenu = menuBar.addMenu("&Settings")
        themesMenu = settingsMenu.addMenu("Theme")
        settingsMenu.addSeparator()
        settingsMenu.addAction(setDestAction)
        settingsMenu.addSeparator()
        settingsMenu.addAction(self.dupeAction)
        settingsMenu.addAction(self.playlistFolderAction)

        ##  Themes submenu
        themesMenu.addAction(defaultThemeAction)
        themesMenu.addAction(lightThemeAction)
        themesMenu.addAction(darkThemeAction)

        ##  Help menu
        helpMenu = menuBar.addMenu("&Help")
        helpMenu.addAction(aboutAction)
Ejemplo n.º 24
0
    def init_UI(self):

        ##  Just to make life easier
        get_icon = Icons().get_icon

        ##  Start all of the widgets
        self.listWidget = ListWidget(self)

        ##  The Destination button
        self.destButton = QPushButton(QIcon(get_icon("folder-open")), "")
        self.destButton.setToolTip("Choose download directory")

        ##  Destination path edit
        self.destEdit = QLineEdit(self.parent.opts["downloadPath"])
        self.destEdit.setToolTip("Path to destination directory")

        ##  The profiles
        self.profileBox = QComboBox(self)
        self.init_profile_box()

        ##  The other buttons
        self.addButton = QPushButton(QIcon(get_icon("list-add")), "")
        self.addButton.setToolTip("Add a URL manually")

        self.removeButton = QPushButton(QIcon(get_icon("list-remove")), "")
        self.removeButton.setToolTip("Remove selected URL")

        self.quickAddButton = QPushButton(QIcon(get_icon("edit-paste")), "")
        self.quickAddButton.setToolTip("Add a URL directly from the clipboard")

        self.goButton = QPushButton(QIcon(get_icon("go-next")), "")
        self.goButton.setToolTip("Download the list of URLs")

        ##  The current progress bar
        self.currentProgressBar = QProgressBar(self)
        self.currentProgressBar.setTextVisible(False)

        ##  The total progress bar
        self.totalProgressBar = QProgressBar(self)
        self.totalProgressBar.setTextVisible(False)

        ##  The free space label
        self.freeLabel = QLabel(self)
        self.update_free_label()

        ##  Connect it up
        self.connect_all()

        ##  The destination layout
        dest = QHBoxLayout()
        dest.addWidget(self.destButton)
        dest.addWidget(self.destEdit, 1)

        ##  Dest + profiles
        dBox = QVBoxLayout()
        dBox.addLayout(dest, 1)
        dBox.addWidget(self.profileBox)

        ##  Free space
        fBox = QHBoxLayout()
        fBox.addWidget(QWidget(), 1)
        fBox.addWidget(self.freeLabel)

        ##  Buttons layout
        hbox = QHBoxLayout()
        hbox.addWidget(QWidget(), 1)
        hbox.addWidget(self.addButton)
        hbox.addWidget(self.quickAddButton)
        hbox.addWidget(self.removeButton)
        hbox.addWidget(self.goButton)

        ##  List label
        listLabel = QHBoxLayout()
        listLabel.addWidget(QLabel("URLs:"))

        ##  List
        lBox = QVBoxLayout()
        lBox.addLayout(listLabel)
        lBox.addWidget(self.listWidget, 1)

        ##  Lay 'em down by the fi-yah
        vbox = QVBoxLayout()
        vbox.addLayout(dBox)
        vbox.addLayout(lBox)
        vbox.addLayout(hbox)

        ##  Progress bars
        #currentProgress = QHBoxLayout()
        #currentProgress.addWidget( QLabel( "Current" ))
        #currentProgress.addWidget( self.currentProgressBar )
        #vbox.addLayout( currentProgress )

        #totalProgress = QHBoxLayout()
        #totalProgress.addWidget( QLabel( "Total" ))
        #totalProgress.addWidget( self.totalProgressBar )
        #vbox.addLayout( totalProgress )
        vbox.addWidget(QLabel("Current"))
        vbox.addWidget(self.currentProgressBar)
        vbox.addWidget(QLabel("Total"))
        vbox.addWidget(self.totalProgressBar)

        vbox.addLayout(fBox)

        ##  Set the layout
        self.setLayout(vbox)
Ejemplo n.º 25
0
 def __initialize_icons(self):
     """Retrieves the icons needed to display within the file view."""
     self.__icons = Icons(self)